Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 20064 Details for
Bug 91938
[ast rewrite] new API: move range of nodes and replace
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
patch
move-nodes.txt (text/plain), 38.85 KB, created by
Martin Aeschlimann
on 2005-04-19 13:04:37 EDT
(
hide
)
Description:
patch
Filename:
MIME Type:
Creator:
Martin Aeschlimann
Created:
2005-04-19 13:04:37 EDT
Size:
38.85 KB
patch
obsolete
>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 <code>null</code>, if a node is not a child of the current list or if the first node >+ * is not before the last node. An <code>IllegalArgumentException</code> 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 <code>null</code>, if a node is not a child of the current list or if the first node >+ * is not before the last node. An <code>IllegalArgumentException</code> 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 <code>null</code> to remove all nodes >+ * @param editGroup the edit group in which to collect the corresponding >+ * text edits fro a replace, or <code>null</code> if ungrouped >+ * @return the new placeholder node >+ * @throws IllegalArgumentException An exception is thrown if the first or >+ * last node are <code>null</code>, if a node is not a child of the current list or >+ * if the first node is not before the last node. An <code>IllegalArgumentException >+ * </code> 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 <PropertyLocation, CopyRangeInfo>)*/ >+ 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); > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 91938
: 20064