Index: dom/org/eclipse/jdt/core/dom/rewrite/ASTRewrite.java
===================================================================
RCS file: /home/eclipse/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ASTRewrite.java,v
retrieving revision 1.19
diff -u -r1.19 ASTRewrite.java
--- dom/org/eclipse/jdt/core/dom/rewrite/ASTRewrite.java 21 Mar 2005 10:31:55 -0000 1.19
+++ dom/org/eclipse/jdt/core/dom/rewrite/ASTRewrite.java 19 Apr 2005 17:03:18 -0000
@@ -178,10 +178,14 @@
if (rootNode != null) {
//validateASTNotModified(rootNode);
- getRewriteEventStore().markMovedNodesRemoved();
+ TargetSourceRangeComputer sourceRangeComputer= getExtendedSourceRangeComputer();
+
+ this.eventStore.prepareMovedNodes(sourceRangeComputer);
- ASTRewriteAnalyzer visitor= new ASTRewriteAnalyzer(document, result, this.eventStore, this.nodeStore, options, getExtendedSourceRangeComputer());
+ ASTRewriteAnalyzer visitor= new ASTRewriteAnalyzer(document, result, this.eventStore, this.nodeStore, options, sourceRangeComputer);
rootNode.accept(visitor); // throws IllegalArgumentException
+
+ this.eventStore.revertMovedNodes();
}
return result;
}
Index: dom/org/eclipse/jdt/core/dom/rewrite/ListRewrite.java
===================================================================
RCS file: /home/eclipse/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ListRewrite.java,v
retrieving revision 1.9
diff -u -r1.9 ListRewrite.java
--- dom/org/eclipse/jdt/core/dom/rewrite/ListRewrite.java 24 Mar 2005 17:25:13 -0000 1.9
+++ dom/org/eclipse/jdt/core/dom/rewrite/ListRewrite.java 19 Apr 2005 17:03:19 -0000
@@ -13,19 +13,18 @@
import java.util.Collections;
import java.util.List;
-import org.eclipse.text.edits.TextEditGroup;
-
import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
-
import org.eclipse.jdt.internal.core.dom.rewrite.ListRewriteEvent;
import org.eclipse.jdt.internal.core.dom.rewrite.NodeInfoStore;
import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEvent;
import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore;
import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore.CopySourceInfo;
+import org.eclipse.text.edits.TextEditGroup;
/**
* For describing manipulations to a child list property of an AST node.
@@ -290,18 +289,19 @@
}
- private ASTNode createTargetNode(ASTNode first, ASTNode last, boolean isMove) {
+ private ASTNode createTargetNode(ASTNode first, ASTNode last, boolean isMove, ASTNode replacingNode, TextEditGroup editGroup) {
if (first == null || last == null) {
throw new IllegalArgumentException();
}
- //validateIsInsideAST(node);
- CopySourceInfo info= getRewriteStore().markAsRangeCopySource(this.parent, this.childProperty, first, last, isMove);
-
+
NodeInfoStore nodeStore= this.rewriter.getNodeStore();
ASTNode placeholder= nodeStore.newPlaceholderNode(first.getNodeType()); // revisit: could use list type
if (placeholder == null) {
throw new IllegalArgumentException("Creating a target node is not supported for nodes of type" + first.getClass().getName()); //$NON-NLS-1$
}
+
+ Block internalPlaceHolder= nodeStore.createCollapsePlaceholder();
+ CopySourceInfo info= getRewriteStore().createRangeCopy(this.parent, this.childProperty, first, last, isMove, internalPlaceHolder, replacingNode, editGroup);
nodeStore.markAsCopyTarget(placeholder, info);
return placeholder;
@@ -318,14 +318,16 @@
* @param first the node that starts the range
* @param last the node that ends the range
* @return the new placeholder node
- * @throws IllegalArgumentException if the node is null, or if the node
- * is not part of this rewriter's AST
+ * @throws IllegalArgumentException An exception is thrown if the first or last node
+ * are null
, if a node is not a child of the current list or if the first node
+ * is not before the last node. An IllegalArgumentException
is
+ * also thrown if the copied range is overlapping with an other moved or copied range.
*/
public final ASTNode createCopyTarget(ASTNode first, ASTNode last) {
if (first == last) {
return this.rewriter.createCopyTarget(first);
} else {
- return createTargetNode(first, last, false);
+ return createTargetNode(first, last, false, null, null);
}
}
@@ -340,16 +342,47 @@
* @param first the node that starts the range
* @param last the node that ends the range
* @return the new placeholder node
- * @throws IllegalArgumentException if the node is null, or if the node
- * is not part of this rewriter's AST
+ * @throws IllegalArgumentException An exception is thrown if the first or last node
+ * are null
, if a node is not a child of the current list or if the first node
+ * is not before the last node. An IllegalArgumentException
is
+ * also thrown if the moved range is overlapping with an other moved or copied range.
*
* @since 3.1
*/
public final ASTNode createMoveTarget(ASTNode first, ASTNode last) {
+ return createMoveTarget(first, last, null, null);
+ }
+
+ /**
+ * Creates and returns a placeholder node for a move of a range of nodes of the
+ * current list. The moved nodes can optionally be replaced by a specified node.
+ *
+ * The placeholder node can either be inserted as new or used to replace an
+ * existing node. When the document is rewritten, a copy of the source code
+ * for the given node range is inserted into the output document at the position
+ * corresponding to the placeholder (indentation is adjusted).
+ *
+ * @param first the node that starts the range
+ * @param last the node that ends the range
+ * @param replacingNode a node that is set at the location of the moved nodes
+ * or null
to remove all nodes
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits fro a replace, or null
if ungrouped
+ * @return the new placeholder node
+ * @throws IllegalArgumentException An exception is thrown if the first or
+ * last node are null
, if a node is not a child of the current list or
+ * if the first node is not before the last node. An IllegalArgumentException
+ *
is also thrown if the moved range is overlapping with an other moved
+ * or copied range.
+ *
+ * @since 3.1
+ */
+ public final ASTNode createMoveTarget(ASTNode first, ASTNode last, ASTNode replacingNode, TextEditGroup editGroup) {
if (first == last) {
+ replace(first, replacingNode, editGroup);
return this.rewriter.createMoveTarget(first);
} else {
- return createTargetNode(first, last, true);
+ return createTargetNode(first, last, true, replacingNode, editGroup);
}
}
Index: dom/org/eclipse/jdt/core/dom/rewrite/TargetSourceRangeComputer.java
===================================================================
RCS file: /home/eclipse/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/TargetSourceRangeComputer.java,v
retrieving revision 1.3
diff -u -r1.3 TargetSourceRangeComputer.java
--- dom/org/eclipse/jdt/core/dom/rewrite/TargetSourceRangeComputer.java 21 Mar 2005 10:31:55 -0000 1.3
+++ dom/org/eclipse/jdt/core/dom/rewrite/TargetSourceRangeComputer.java 19 Apr 2005 17:03:19 -0000
@@ -125,9 +125,11 @@
* that should be replaced (or deleted)
*/
public SourceRange computeSourceRange(ASTNode node) {
- CompilationUnit cu = (CompilationUnit) node.getRoot();
- return new SourceRange(
- cu.getExtendedStartPosition(node),
- cu.getExtendedLength(node));
+ ASTNode root= node.getRoot();
+ if (root instanceof CompilationUnit) {
+ CompilationUnit cu= (CompilationUnit) root;
+ return new SourceRange(cu.getExtendedStartPosition(node), cu.getExtendedLength(node));
+ }
+ return new SourceRange(node.getStartPosition(), node.getLength());
}
}
Index: dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
===================================================================
RCS file: /home/eclipse/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java,v
retrieving revision 1.29
diff -u -r1.29 ASTRewriteAnalyzer.java
--- dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java 7 Apr 2005 08:41:39 -0000 1.29
+++ dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java 19 Apr 2005 17:03:21 -0000
@@ -114,41 +114,33 @@
}
/**
- * Returns the extended source range computer for this AST rewriter.
+ * Returns the extended source range for a node.
*
- * @return an extended source range computer (never null)
+ * @return an extended source range (never null)
* @since 3.1
*/
- private TargetSourceRangeComputer getExtendedSourceRangeComputer() {
- return this.extendedSourceRangeComputer;
- }
-
final SourceRange getExtendedRange(ASTNode node) {
- return getExtendedSourceRangeComputer().computeSourceRange(node);
+ if (node.getParent() == null) {
+ return new SourceRange(node.getStartPosition(), node.getLength());
+ }
+ return this.extendedSourceRangeComputer.computeSourceRange(node);
}
final int getExtendedOffset(ASTNode node) {
- return getExtendedSourceRangeComputer().computeSourceRange(node).getStartPosition();
+ return getExtendedRange(node).getStartPosition();
}
final int getExtendedEnd(ASTNode node) {
- TargetSourceRangeComputer.SourceRange range =
- getExtendedSourceRangeComputer().computeSourceRange(node);
+ TargetSourceRangeComputer.SourceRange range= getExtendedRange(node);
return range.getStartPosition() + range.getLength();
}
final TextEdit getCopySourceEdit(CopySourceInfo info) {
TextEdit edit= (TextEdit) this.sourceCopyInfoToEdit.get(info);
if (edit == null) {
- int start, end;
- if (info.getStartNode() == info.getEndNode()) {
- SourceRange range= getExtendedRange(info.getStartNode());
- start= range.getStartPosition();
- end= start + range.getLength();
- } else {
- start= getExtendedOffset(info.getStartNode());
- end= getExtendedEnd(info.getEndNode());
- }
+ SourceRange range= getExtendedRange(info.getNode());
+ int start= range.getStartPosition();
+ int end= start + range.getLength();
if (info.isMove) {
MoveSourceEdit moveSourceEdit= new MoveSourceEdit(start, end - start);
moveSourceEdit.setTargetEdit(new MoveTargetEdit(0));
@@ -284,32 +276,18 @@
if (property.isChildProperty() && node != null) {
return doVisit((ASTNode) node);
} else if (property.isChildListProperty()) {
- boolean hasRangeCopySources= this.eventStore.hasRangeCopySources(parent, property);
- return doVisitList((List) node, offset, hasRangeCopySources);
+ return doVisitList((List) node, offset);
}
return offset;
}
- private int doVisitList(List list, int offset, boolean hasRangeCopySources) {
- if (hasRangeCopySources) {
- // list with copy source ranges
- Stack nodeRangeEndStack= new Stack();
- int endPos= offset;
- for (Iterator iter= list.iterator(); iter.hasNext();) {
- ASTNode curr= ((ASTNode) iter.next());
- doCopySourcePreVisit(this.eventStore.getRangeCopySources(curr), nodeRangeEndStack);
- endPos= doVisit(curr);
- doCopySourcePostVisit(curr, nodeRangeEndStack);
- }
- return endPos;
- } else {
- int endPos= offset;
- for (Iterator iter= list.iterator(); iter.hasNext();) {
- ASTNode curr= ((ASTNode) iter.next());
- endPos= doVisit(curr);
- }
- return endPos;
+ private int doVisitList(List list, int offset) {
+ int endPos= offset;
+ for (Iterator iter= list.iterator(); iter.hasNext();) {
+ ASTNode curr= ((ASTNode) iter.next());
+ endPos= doVisit(curr);
}
+ return endPos;
}
final void voidVisit(ASTNode node) {
@@ -321,42 +299,20 @@
if (property.isChildProperty() && node != null) {
voidVisit((ASTNode) node);
} else if (property.isChildListProperty()) {
- boolean hasRangeCopySources= this.eventStore.hasRangeCopySources(parent, property);
- voidVisitList((List) node, hasRangeCopySources);
+ voidVisitList((List) node);
}
}
- private void voidVisitList(List list, boolean hasRangeCopySources) {
- if (hasRangeCopySources) {
- // list with copy source ranges
- Stack nodeRangeEndStack= new Stack();
- for (Iterator iter= list.iterator(); iter.hasNext();) {
- ASTNode curr= ((ASTNode) iter.next());
- doCopySourcePreVisit(this.eventStore.getRangeCopySources(curr), nodeRangeEndStack);
- doVisit(curr);
- doCopySourcePostVisit(curr, nodeRangeEndStack);
- }
- } else {
- for (Iterator iter= list.iterator(); iter.hasNext();) {
- doVisit(((ASTNode) iter.next()));
- }
+ private void voidVisitList(List list) {
+ for (Iterator iter= list.iterator(); iter.hasNext();) {
+ doVisit(((ASTNode) iter.next()));
}
}
private final boolean doVisitUnchangedChildren(ASTNode parent) {
List properties= parent.structuralPropertiesForType();
for (int i= 0; i < properties.size(); i++) {
- StructuralPropertyDescriptor property= (StructuralPropertyDescriptor) properties.get(i);
- if (property.isChildProperty()) {
- ASTNode child= (ASTNode) parent.getStructuralProperty(property);
- if (child != null) {
- voidVisit(child);
- }
- } else if (property.isChildListProperty()) {
- List list= (List) parent.getStructuralProperty(property);
- boolean hasRangeCopySources= this.eventStore.hasRangeCopySources(parent, property);
- voidVisitList(list, hasRangeCopySources);
- }
+ voidVisit(parent, (StructuralPropertyDescriptor) properties.get(i));
}
return false;
}
@@ -409,8 +365,6 @@
protected RewriteEvent[] list;
- private Stack copyRangeEndStack;
-
protected final ASTNode getOriginalNode(int index) {
return (ASTNode) this.list[index].getOriginalValue();
}
@@ -465,8 +419,6 @@
this.startPos= offset;
this.list= getEvent(parent, property).getChildren();
- initCopyRangeChecks(parent, property);
-
int total= this.list.length;
if (total == 0) {
return this.startPos;
@@ -543,17 +495,13 @@
if (i > lastNonDelete && separatorState == EXISTING) {
// is last, remove previous separator: split delete to allow range copies
doTextRemove(prevEnd, currPos - prevEnd, editGroup); // remove separator
- checkForRangeStart(node);
doTextRemoveAndVisit(currPos, currEnd - currPos, node, editGroup); // remove node
- checkForRangeEnd(node);
currPos= currEnd;
prevEnd= currEnd;
} else {
// remove element and next separator
int end= getStartOfNextNode(nextIndex, currEnd); // start of next
- checkForRangeStart(node);
doTextRemoveAndVisit(currPos, currEnd - currPos, node, getEditGroup(currEvent)); // remove node
- checkForRangeEnd(node);
doTextRemove(currEnd, end - currEnd, editGroup); // remove separator
currPos= end;
prevEnd= currEnd;
@@ -566,17 +514,13 @@
TextEditGroup editGroup= getEditGroup(currEvent);
ASTNode changed= (ASTNode) currEvent.getNewValue();
- checkForRangeStart(node);
doTextRemoveAndVisit(currPos, currEnd - currPos, node, editGroup);
doTextInsert(currPos, changed, getNodeIndent(i), true, editGroup);
- checkForRangeEnd(node);
prevEnd= currEnd;
} else { // is unchanged
ASTNode node= (ASTNode) currEvent.getOriginalValue();
- checkForRangeStart(node);
voidVisit(node);
- checkForRangeEnd(node);
}
if (i == lastNonInsert) { // last node or next nodes are all inserts
separatorState= NONE;
@@ -600,23 +544,6 @@
return currPos;
}
- private void initCopyRangeChecks(ASTNode parent, StructuralPropertyDescriptor property) {
- if (ASTRewriteAnalyzer.this.eventStore.hasRangeCopySources(parent, property)) {
- this.copyRangeEndStack= new Stack();
- }
- }
-
- private void checkForRangeStart(ASTNode node) {
- if (this.copyRangeEndStack != null) {
- doCopySourcePreVisit(ASTRewriteAnalyzer.this.eventStore.getRangeCopySources(node), this.copyRangeEndStack);
- }
- }
-
- private void checkForRangeEnd(ASTNode node) {
- if (this.copyRangeEndStack != null) {
- doCopySourcePostVisit(node, this.copyRangeEndStack);
- }
- }
}
private int rewriteRequiredNode(ASTNode parent, StructuralPropertyDescriptor property) {
@@ -1109,7 +1036,7 @@
String destIndentString= this.formatter.getIndentString(getCurrentLine(formatted, offset));
if (data instanceof CopyPlaceholderData) { // replace with a copy/move target
CopySourceInfo copySource= ((CopyPlaceholderData) data).copySource;
- int srcIndentLevel= getIndent(copySource.getStartNode().getStartPosition());
+ int srcIndentLevel= getIndent(copySource.getNode().getStartPosition());
TextEdit sourceEdit= getCopySourceEdit(copySource);
doTextCopy(sourceEdit, insertOffset, srcIndentLevel, destIndentString, editGroup);
currPos= offset + curr.length; // continue to insert after the replaced string
@@ -1297,7 +1224,7 @@
TextEdit edit= getCopySourceEdit(curr);
addEdit(edit);
this.currentEdit= edit;
- nodeEndStack.push(curr.getEndNode());
+ nodeEndStack.push(curr.getNode());
}
}
}
Index: dom/org/eclipse/jdt/internal/core/dom/rewrite/RewriteEventStore.java
===================================================================
RCS file: /home/eclipse/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/RewriteEventStore.java,v
retrieving revision 1.7
diff -u -r1.7 RewriteEventStore.java
--- dom/org/eclipse/jdt/internal/core/dom/rewrite/RewriteEventStore.java 24 Mar 2005 17:25:13 -0000 1.7
+++ dom/org/eclipse/jdt/internal/core/dom/rewrite/RewriteEventStore.java 19 Apr 2005 17:03:23 -0000
@@ -10,23 +10,12 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core.dom.rewrite;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.eclipse.text.edits.TextEditGroup;
+import java.util.*;
import org.eclipse.jdt.core.Signature;
-
-import org.eclipse.jdt.core.dom.ASTNode;
-import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
+import org.eclipse.jdt.core.dom.*;
+import org.eclipse.jdt.core.dom.rewrite.TargetSourceRangeComputer;
+import org.eclipse.text.edits.TextEditGroup;
/**
@@ -37,8 +26,8 @@
public final class PropertyLocation {
- private ASTNode parent;
- private StructuralPropertyDescriptor property;
+ private final ASTNode parent;
+ private final StructuralPropertyDescriptor property;
public PropertyLocation(ASTNode parent, StructuralPropertyDescriptor property) {
this.parent= parent;
@@ -52,6 +41,19 @@
public StructuralPropertyDescriptor getProperty() {
return this.property;
}
+
+ public boolean equals(Object obj) {
+ if (obj != null && obj.getClass().equals(this.getClass())) {
+ PropertyLocation other= (PropertyLocation) obj;
+ return other.getParent().equals(getParent()) && other.getProperty().equals(getProperty());
+ }
+ return false;
+ }
+
+ public int hashCode() {
+ return getParent().hashCode() + getProperty().hashCode();
+ }
+
}
/**
@@ -92,19 +94,60 @@
}
}
- public static class CopySourceInfo {
- public final ASTNode parent;
- public final StructuralPropertyDescriptor childProperty;
+ public static class CopySourceInfo implements Comparable {
+ public final PropertyLocation location; // can be null, only used to mark as removed on move
+ private final ASTNode node;
+ public final boolean isMove;
+
+ public CopySourceInfo(PropertyLocation location, ASTNode node, boolean isMove) {
+ this.location= location;
+ this.node= node;
+ this.isMove= isMove;
+ }
+
+ public ASTNode getNode() {
+ return this.node;
+ }
+
+ public int compareTo(Object o2) {
+ CopySourceInfo r2= (CopySourceInfo) o2;
+
+ int startDiff= this.getNode().getStartPosition() - r2.getNode().getStartPosition();
+ if (startDiff != 0) {
+ return startDiff; // insert before if start node is first
+ }
+
+ if (r2.isMove != this.isMove) {
+ return this.isMove ? -1 : 1; // first move then copy
+ }
+ return 0;
+ }
+
+ public String toString() {
+ StringBuffer buf= new StringBuffer();
+ if (this.isMove) {
+ buf.append("move source: "); //$NON-NLS-1$
+ } else {
+ buf.append("copy source: "); //$NON-NLS-1$
+ }
+ buf.append(this.node);
+ return buf.toString();
+ }
+ }
+
+ private static class NodeRangeInfo implements Comparable {
private final ASTNode first;
private final ASTNode last;
- public final boolean isMove;
+ public final CopySourceInfo copyInfo; // containing the internal placeholder and the 'isMove' flag
+ public final ASTNode replacingNode;
+ public final TextEditGroup editGroup;
- public CopySourceInfo(ASTNode parent, StructuralPropertyDescriptor childProperty, ASTNode first, ASTNode last, boolean isMove) {
- this.parent= parent;
- this.childProperty= childProperty;
+ public NodeRangeInfo(ASTNode parent, StructuralPropertyDescriptor childProperty, ASTNode first, ASTNode last, CopySourceInfo copyInfo, ASTNode replacingNode, TextEditGroup editGroup) {
this.first= first;
this.last= last;
- this.isMove= isMove;
+ this.copyInfo= copyInfo;
+ this.replacingNode= replacingNode;
+ this.editGroup= editGroup;
}
public ASTNode getStartNode() {
@@ -114,39 +157,59 @@
public ASTNode getEndNode() {
return this.last;
}
-
+
+ public boolean isMove() {
+ return this.copyInfo.isMove;
+ }
+
+ public Block getInternalPlaceholder() {
+ return (Block) this.copyInfo.getNode();
+ }
+
+ public int compareTo(Object o2) {
+ NodeRangeInfo r2= (NodeRangeInfo) o2;
+
+ int startDiff= this.getStartNode().getStartPosition() - r2.getStartNode().getStartPosition();
+ if (startDiff != 0) {
+ return startDiff; // insert before if start node is first
+ }
+ int endDiff= this.getEndNode().getStartPosition() - r2.getEndNode().getStartPosition();
+ if (endDiff != 0) {
+ return -endDiff; // insert before if length is longer
+ }
+ if (r2.isMove() != this.isMove()) {
+ return this.isMove() ? -1 : 1; // first move then copy
+ }
+ return 0;
+ }
+
+ public void updatePlaceholderSourceRanges(TargetSourceRangeComputer sourceRangeComputer) {
+ TargetSourceRangeComputer.SourceRange startRange= sourceRangeComputer.computeSourceRange(getStartNode());
+ TargetSourceRangeComputer.SourceRange endRange= sourceRangeComputer.computeSourceRange(getEndNode());
+ int startPos= startRange.getStartPosition();
+ int endPos= endRange.getStartPosition() + endRange.getLength();
+
+ Block internalPlaceholder= getInternalPlaceholder();
+ internalPlaceholder.setSourceRange(startPos, endPos - startPos);
+ }
+
public String toString() {
StringBuffer buf= new StringBuffer();
if (this.first != this.last) {
buf.append("range "); //$NON-NLS-1$
}
- if (this.isMove) {
+ if (isMove()) {
buf.append("move source: "); //$NON-NLS-1$
} else {
buf.append("copy source: "); //$NON-NLS-1$
}
buf.append(this.first);
- if (this.first != this.last) {
- buf.append(" - "); //$NON-NLS-1$
- buf.append(this.last);
- }
+ buf.append(" - "); //$NON-NLS-1$
+ buf.append(this.last);
return buf.toString();
}
- }
- public static class CopySourceInfoSorter implements Comparator {
- public int compare(Object o1, Object o2) {
- CopySourceInfo e1= (CopySourceInfo) o1;
- CopySourceInfo e2= (CopySourceInfo) o2;
- if (e1.isMove) {
- return -1;
- } else if (e2.isMove) {
- return 1;
- }
- return e2.getEndNode().getStartPosition() - e1.getEndNode().getStartPosition();
- }
-
}
/**
@@ -166,8 +229,8 @@
} else {
this.sourceNodeIter= Collections.EMPTY_LIST.iterator();
}
- if (RewriteEventStore.this.rangeCopySources != null) {
- this.rangeNodeIter= RewriteEventStore.this.rangeCopySources.iterator();
+ if (RewriteEventStore.this.nodeRangeInfos != null) {
+ this.rangeNodeIter= RewriteEventStore.this.nodeRangeInfos.keySet().iterator();
} else {
this.rangeNodeIter= Collections.EMPTY_LIST.iterator();
}
@@ -193,10 +256,10 @@
return ((EventHolder) this.eventIter.next()).parent;
}
if (this.sourceNodeIter.hasNext()) {
- return ((CopySourceInfo) this.sourceNodeIter.next()).getStartNode();
+ return ((CopySourceInfo) this.sourceNodeIter.next()).getNode();
}
if (this.rangeNodeIter.hasNext()) {
- return ((CopySourceInfo) this.rangeNodeIter.next()).parent;
+ return ((PropertyLocation) this.rangeNodeIter.next()).getParent();
}
return this.trackedNodeIter.next();
}
@@ -223,11 +286,11 @@
/** Maps events to group descriptions */
private Map editGroups;
- /** Stores which nodes are source of a copy or move (list of CopyRangeSourceInfo)*/
+ /** Stores which nodes are source of a copy or move (list of CopySourceInfo)*/
List nodeCopySources;
- /** Stores which node ranges that are source of a copy or move (list of CopyRangeSourceInfo)*/
- List rangeCopySources;
+ /** Stores node ranges that are used to copy or move (map of )*/
+ Map nodeRangeInfos;
/** Stores which nodes are tracked and the corresponding edit group*/
Map trackedNodes;
@@ -250,6 +313,7 @@
this.nodePropertyMapper= null;
this.nodeCopySources= null;
+ this.nodeRangeInfos= null;
}
/**
@@ -485,8 +549,8 @@
setTrackedNodeData(node, editGroup);
}
- public final CopySourceInfo markAsCopySource(ASTNode parent, StructuralPropertyDescriptor property, ASTNode node, boolean isMove) {
- CopySourceInfo copySource= new CopySourceInfo(parent, property, node, node, isMove);
+ private final CopySourceInfo createCopySourceInfo(PropertyLocation location, ASTNode node, boolean isMove) {
+ CopySourceInfo copySource= new CopySourceInfo(location, node, isMove);
if (this.nodeCopySources == null) {
this.nodeCopySources= new ArrayList();
@@ -495,18 +559,47 @@
return copySource;
}
- public final CopySourceInfo markAsRangeCopySource(ASTNode parent, StructuralPropertyDescriptor property, ASTNode first, ASTNode last, boolean isMove) {
- CopySourceInfo copySource= new CopySourceInfo(parent, property, first, last, isMove);
- assertNoOverlap(copySource);
+ public final CopySourceInfo markAsCopySource(ASTNode parent, StructuralPropertyDescriptor property, ASTNode node, boolean isMove) {
+ return createCopySourceInfo(new PropertyLocation(parent, property), node, isMove);
+ }
+
+ public final CopySourceInfo createRangeCopy(ASTNode parent, StructuralPropertyDescriptor childProperty, ASTNode first, ASTNode last, boolean isMove, ASTNode internalPlaceholder, ASTNode replacingNode, TextEditGroup editGroup) {
+ CopySourceInfo copyInfo= createCopySourceInfo(null, internalPlaceholder, isMove);
- if (this.rangeCopySources == null) {
- this.rangeCopySources= new ArrayList();
+ NodeRangeInfo copyRangeInfo= new NodeRangeInfo(parent, childProperty, first, last, copyInfo, replacingNode, editGroup);
+
+ ListRewriteEvent listEvent= getListEvent(parent, childProperty, true);
+
+ int indexFirst= listEvent.getIndex(first, ListRewriteEvent.OLD);
+ if (indexFirst == -1) {
+ throw new IllegalArgumentException("Start node is not a original child of the given list"); //$NON-NLS-1$
}
- this.rangeCopySources.add(copySource);
- return copySource;
+ int indexLast= listEvent.getIndex(last, ListRewriteEvent.OLD);
+ if (indexLast == -1) {
+ throw new IllegalArgumentException("End node is not a original child of the given list"); //$NON-NLS-1$
+ }
+
+ if (indexFirst > indexLast) {
+ throw new IllegalArgumentException("Start node must be before end node"); //$NON-NLS-1$
+ }
+
+ if (this.nodeRangeInfos == null) {
+ this.nodeRangeInfos= new HashMap();
+ }
+ PropertyLocation loc= new PropertyLocation(parent, childProperty);
+ List innerList= (List) this.nodeRangeInfos.get(loc);
+ if (innerList == null) {
+ innerList= new ArrayList(2);
+ this.nodeRangeInfos.put(loc, innerList);
+ } else {
+ assertNoOverlap(listEvent, indexFirst, indexLast, innerList);
+ }
+ innerList.add(copyRangeInfo);
+
+
+ return copyInfo;
}
-
public CopySourceInfo[] getNodeCopySources(ASTNode node) {
if (this.nodeCopySources == null) {
return null;
@@ -514,105 +607,172 @@
return internalGetCopySources(this.nodeCopySources, node);
}
- public CopySourceInfo[] getRangeCopySources(ASTNode node) {
- if (this.rangeCopySources == null) {
- return null;
- }
- return internalGetCopySources(this.rangeCopySources, node);
- }
-
- public boolean hasRangeCopySources(ASTNode parent, StructuralPropertyDescriptor property) {
- if (this.rangeCopySources == null) {
- return false;
- }
- for (int i= 0; i < this.rangeCopySources.size(); i++) {
- CopySourceInfo curr= (CopySourceInfo) this.rangeCopySources.get(i);
- if (curr.parent == parent && curr.childProperty == property) {
- return true;
- }
- }
- return false;
- }
public CopySourceInfo[] internalGetCopySources(List copySources, ASTNode node) {
ArrayList res= new ArrayList(3);
for (int i= 0; i < copySources.size(); i++) {
CopySourceInfo curr= (CopySourceInfo) copySources.get(i);
- if (curr.getStartNode() == node) {
+ if (curr.getNode() == node) {
res.add(curr);
}
}
if (res.isEmpty()) {
return null;
}
+
CopySourceInfo[] arr= (CopySourceInfo[]) res.toArray(new CopySourceInfo[res.size()]);
- if (arr.length > 1) {
- Arrays.sort(arr, new CopySourceInfoSorter());
- }
+ Arrays.sort(arr);
return arr;
}
- private void assertNoOverlap(CopySourceInfo copySource) {
- ASTNode parent= copySource.parent;
- StructuralPropertyDescriptor childProperty= copySource.childProperty;
- ASTNode first= copySource.getStartNode();
- ASTNode last= copySource.getEndNode();
-
- ListRewriteEvent listEvent= getListEvent(parent, childProperty, true);
+ private void assertNoOverlap(ListRewriteEvent listEvent, int indexFirst, int indexLast, List innerList) {
+ for (Iterator iter= innerList.iterator(); iter.hasNext();) {
+ NodeRangeInfo curr= (NodeRangeInfo) iter.next();
+ int currStart= listEvent.getIndex(curr.getStartNode(), ListRewriteEvent.BOTH);
+ int currEnd= listEvent.getIndex(curr.getEndNode(), ListRewriteEvent.BOTH);
+ if (currStart < indexFirst && currEnd < indexLast && currEnd >= indexFirst
+ || currStart > indexFirst && currStart <= currEnd && currEnd > indexLast) {
+ throw new IllegalArgumentException("Range overlapps with an existing copy or move range"); //$NON-NLS-1$
+ }
+ }
+ }
+
+ public void prepareMovedNodes(TargetSourceRangeComputer sourceRangeComputer) {
+ if (this.nodeCopySources != null) {
+ prepareSingleNodeCopies();
+ }
- int indexFirst= listEvent.getIndex(first, ListRewriteEvent.OLD);
- if (indexFirst == -1) {
- throw new IllegalArgumentException("Start node is not a original child of the given list"); //$NON-NLS-1$
+ if (this.nodeRangeInfos != null) {
+ prepareNodeRangeCopies(sourceRangeComputer);
}
- int indexLast= listEvent.getIndex(last, ListRewriteEvent.OLD);
- if (indexLast == -1) {
- throw new IllegalArgumentException("End node is not a original child of the given list"); //$NON-NLS-1$
+ }
+
+ public void revertMovedNodes() {
+ if (this.nodeRangeInfos != null) {
+ removeMoveRangePlaceholders();
}
-
- if (indexFirst > indexLast) {
- throw new IllegalArgumentException("Start node must be before end node"); //$NON-NLS-1$
+ }
+
+ private void removeMoveRangePlaceholders() {
+ for (Iterator iter= this.nodeRangeInfos.entrySet().iterator(); iter.hasNext();) {
+ Map.Entry entry= (Map.Entry) iter.next();
+ Set placeholders= new HashSet(); // collect all placeholders
+ List rangeInfos= (List) entry.getValue(); // list of CopySourceRange
+ for (int i= 0; i < rangeInfos.size(); i++) {
+ placeholders.add(((NodeRangeInfo) rangeInfos.get(i)).getInternalPlaceholder());
+ }
+
+ PropertyLocation loc= (PropertyLocation) entry.getKey();
+
+ RewriteEvent[] children= getListEvent(loc.getParent(), loc.getProperty(), true).getChildren();
+ List revertedChildren= new ArrayList();
+ revertListWithRanges(children, placeholders, revertedChildren);
+ RewriteEvent[] revertedChildrenArr= (RewriteEvent[]) revertedChildren.toArray(new RewriteEvent[revertedChildren.size()]);
+ addEvent(loc.getParent(), loc.getProperty(), new ListRewriteEvent(revertedChildrenArr)); // replace the current edits
+ }
+ }
+
+ private void revertListWithRanges(RewriteEvent[] childEvents, Set placeholders, List revertedChildren) {
+ for (int i= 0; i < childEvents.length; i++) {
+ RewriteEvent event= childEvents[i];
+ ASTNode node= (ASTNode) event.getOriginalValue();
+ if (placeholders.contains(node)) {
+ RewriteEvent[] placeholderChildren= getListEvent(node, Block.STATEMENTS_PROPERTY, false).getChildren();
+ revertListWithRanges(placeholderChildren, placeholders, revertedChildren);
+ } else {
+ revertedChildren.add(event);
+ }
}
- if (this.rangeCopySources != null) {
- for (Iterator iter= this.rangeCopySources.iterator(); iter.hasNext();) {
- CopySourceInfo info= (CopySourceInfo) iter.next();
- if (info.parent == parent && info.childProperty == childProperty) {
- int currStart= listEvent.getIndex(first, ListRewriteEvent.BOTH);
- int currEnd= listEvent.getIndex(first, ListRewriteEvent.BOTH);
- if (currStart < indexFirst && currEnd < indexLast && currEnd >= indexFirst
- || currStart > indexFirst && currStart <= currEnd && currEnd > indexLast) {
- throw new IllegalArgumentException("Range overlapps with an existing copy or move range"); //$NON-NLS-1$
- }
+ }
+
+ private void prepareNodeRangeCopies(TargetSourceRangeComputer sourceRangeComputer) {
+ for (Iterator iter= this.nodeRangeInfos.entrySet().iterator(); iter.hasNext();) {
+ Map.Entry entry= (Map.Entry) iter.next();
+ List rangeInfos= (List) entry.getValue(); // list of CopySourceRange
+ Collections.sort(rangeInfos); // sort by start index, length, move or copy
+
+ PropertyLocation loc= (PropertyLocation) entry.getKey();
+ RewriteEvent[] children= getListEvent(loc.getParent(), loc.getProperty(), true).getChildren();
+
+ RewriteEvent[] newChildren= processListWithRanges(rangeInfos, children, sourceRangeComputer);
+ addEvent(loc.getParent(), loc.getProperty(), new ListRewriteEvent(newChildren)); // replace the current edits
+ }
+ }
+
+ private RewriteEvent[] processListWithRanges(List rangeInfos, RewriteEvent[] childEvents, TargetSourceRangeComputer sourceRangeComputer) {
+ List newChildEvents= new ArrayList(childEvents.length);
+ NodeRangeInfo topInfo= null;
+ Stack newChildrenStack= new Stack();
+ Stack topInfoStack= new Stack();
+
+ Iterator rangeInfoIterator= rangeInfos.iterator();
+ NodeRangeInfo nextInfo= (NodeRangeInfo) rangeInfoIterator.next();
+
+ for (int k= 0; k < childEvents.length; k++) {
+ RewriteEvent event= childEvents[k];
+ ASTNode node= (ASTNode) event.getOriginalValue();
+ // check for ranges and add a placeholder for them
+ while (nextInfo != null && node == nextInfo.getStartNode()) { // is this child the beginning of a range?
+ nextInfo.updatePlaceholderSourceRanges(sourceRangeComputer);
+
+ Block internalPlaceholder= nextInfo.getInternalPlaceholder();
+ RewriteEvent newEvent;
+ if (nextInfo.isMove()) {
+ newEvent= new NodeRewriteEvent(internalPlaceholder, nextInfo.replacingNode); // remove or replace
+ } else {
+ newEvent= new NodeRewriteEvent(internalPlaceholder, internalPlaceholder); // unchanged
+ }
+ newChildEvents.add(newEvent);
+ if (nextInfo.editGroup != null) {
+ setEventEditGroup(newEvent, nextInfo.editGroup);
}
+
+ newChildrenStack.push(newChildEvents);
+ topInfoStack.push(topInfo);
+
+ newChildEvents= new ArrayList(childEvents.length);
+ topInfo= nextInfo;
+
+ nextInfo= rangeInfoIterator.hasNext() ? (NodeRangeInfo) rangeInfoIterator.next() : null;
+ }
+
+ newChildEvents.add(event);
+
+ while (topInfo != null && node == topInfo.getEndNode()) {
+ RewriteEvent[] placeholderChildEvents= (RewriteEvent[]) newChildEvents.toArray(new RewriteEvent[newChildEvents.size()]);
+ Block internalPlaceholder= topInfo.getInternalPlaceholder();
+ addEvent(internalPlaceholder, Block.STATEMENTS_PROPERTY, new ListRewriteEvent(placeholderChildEvents));
+
+ newChildEvents= (List) newChildrenStack.pop();
+ topInfo= (NodeRangeInfo) topInfoStack.pop();
}
}
+ return (RewriteEvent[]) newChildEvents.toArray(new RewriteEvent[newChildEvents.size()]);
}
-
+
/**
* Make sure all moved nodes are marked as removed or replaced.
*/
- public void markMovedNodesRemoved() {
- if (this.nodeCopySources == null) {
- return;
- }
+ private void prepareSingleNodeCopies() {
for (int i= 0; i < this.nodeCopySources.size(); i++) {
CopySourceInfo curr= (CopySourceInfo) this.nodeCopySources.get(i);
- if (curr.isMove) {
- doMarkMovedAsRemoved(curr);
+ if (curr.isMove && curr.location != null) {
+ doMarkMovedAsRemoved(curr, curr.location.getParent(), curr.location.getProperty());
}
}
}
- private void doMarkMovedAsRemoved(CopySourceInfo curr) {
- if (curr.childProperty.isChildListProperty()) {
- ListRewriteEvent event= getListEvent(curr.parent, curr.childProperty, true);
- int index= event.getIndex(curr.getStartNode(), ListRewriteEvent.OLD);
+ private void doMarkMovedAsRemoved(CopySourceInfo curr, ASTNode parent, StructuralPropertyDescriptor childProperty) {
+ if (childProperty.isChildListProperty()) {
+ ListRewriteEvent event= getListEvent(parent, childProperty, true);
+ int index= event.getIndex(curr.getNode(), ListRewriteEvent.OLD);
if (index != -1 && event.getChangeKind(index) == RewriteEvent.UNCHANGED) {
event.setNewValue(null, index);
}
} else {
- NodeRewriteEvent event= getNodeEvent(curr.parent, curr.childProperty, true);
+ NodeRewriteEvent event= getNodeEvent(parent, childProperty, true);
if (event.getChangeKind() == RewriteEvent.UNCHANGED) {
event.setNewValue(null);
}