1 11 package org.eclipse.jdt.internal.corext.dom; 12 13 import java.util.ArrayList ; 14 import java.util.HashMap ; 15 import java.util.HashSet ; 16 import java.util.Iterator ; 17 import java.util.List ; 18 import java.util.Map ; 19 import java.util.Set ; 20 21 import org.eclipse.text.edits.TextEdit; 22 import org.eclipse.text.edits.TextEditGroup; 23 24 import org.eclipse.jface.text.IDocument; 25 26 import org.eclipse.jdt.core.dom.ASTNode; 27 import org.eclipse.jdt.core.dom.Block; 28 import org.eclipse.jdt.core.dom.FieldDeclaration; 29 import org.eclipse.jdt.core.dom.Statement; 30 import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor; 31 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; 32 33 import org.eclipse.jdt.internal.core.dom.rewrite.ListRewriteEvent; 34 import org.eclipse.jdt.internal.core.dom.rewrite.NodeRewriteEvent; 35 import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEvent; 36 import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore; 37 import org.eclipse.jdt.internal.corext.Assert; 38 import org.eclipse.jdt.internal.corext.textmanipulation.TextBuffer; 39 40 import org.eclipse.jdt.internal.ui.JavaPlugin; 41 42 46 public final class OldASTRewrite extends ASTRewrite { 48 private HashMap fChangedProperties; 49 50 private boolean fHasASTModifications; 51 private ASTNode fRootNode; 52 53 57 public OldASTRewrite(ASTNode node) { 58 super(node.getAST()); 59 fRootNode= node; 60 fChangedProperties= new HashMap (); 61 62 fHasASTModifications= false; 63 64 getRewriteEventStore().setNodePropertyMapper(new RewriteEventStore.INodePropertyMapper() { 66 public Object getOriginalValue(ASTNode parent, StructuralPropertyDescriptor childProperty) { 67 Object originalValue= parent.getStructuralProperty(childProperty); 68 if (parent.getStartPosition() == -1) { 69 return originalValue; } 71 if (originalValue instanceof List ) { 72 List originalList= (List ) originalValue; 73 ArrayList fixedList= new ArrayList (originalList.size()); 74 for (int i= 0; i < originalList.size(); i++) { 75 ASTNode curr= (ASTNode) originalList.get(i); 76 if (!isInserted(curr)) { 77 fixedList.add(curr); 78 } 79 } 80 return fixedList; 81 } else if (originalValue instanceof ASTNode) { 82 if (isInserted((ASTNode) originalValue)) { 83 return null; 84 } 85 } 86 return originalValue; 87 } 88 }); 89 } 90 91 99 public final void rewriteNode(TextBuffer textBuffer, TextEdit rootEdit) { 100 try { 101 TextEdit res= rewriteAST(textBuffer.getDocument(), null); 102 rootEdit.addChildren(res.removeChildren()); 103 } catch (IllegalArgumentException e) { 104 JavaPlugin.log(e); 105 } 106 } 107 108 111 public TextEdit rewriteAST(IDocument document, Map options) { 112 convertOldToNewEvents(); 113 return super.rewriteAST(document, options); 114 } 115 116 122 public ASTNode getRootNode() { 123 return fRootNode; 124 } 125 126 130 private void convertOldToNewEvents() { 131 Set processedListEvents= new HashSet (); 132 133 for (Iterator iter= fChangedProperties.keySet().iterator(); iter.hasNext(); ) { 134 ASTNode node= (ASTNode) iter.next(); 135 ASTInsert object= getChangeProperty(node); 136 if (object != null) { 137 if (node.getParent().getStartPosition() != -1) { processChange(node, null, node, object.description, processedListEvents); 139 if (object.isBoundToPrevious) { 140 getRewriteEventStore().setInsertBoundToPrevious(node); 141 } 142 } 143 } 144 } 145 } 146 147 private void processChange(ASTNode nodeInAST, ASTNode originalNode, ASTNode newNode, TextEditGroup desc, Set processedListEvents) { 148 ASTNode parent= nodeInAST.getParent(); 149 StructuralPropertyDescriptor childProperty= nodeInAST.getLocationInParent(); 150 if (childProperty.isChildListProperty()) { 151 ListRewriteEvent event= getRewriteEventStore().getListEvent(parent, childProperty, true); if (processedListEvents.add(event)) { 153 convertListChange(event, (List ) parent.getStructuralProperty(childProperty)); 154 } 155 } else { 156 NodeRewriteEvent event= getRewriteEventStore().getNodeEvent(parent, childProperty, true); 157 event.setNewValue(newNode); 158 getRewriteEventStore().setEventEditGroup(event, desc); 159 } 160 } 161 162 163 private void convertListChange(ListRewriteEvent listEvent, List modifiedList) { 164 for (int i= 0; i < modifiedList.size(); i++) { 165 ASTNode curr= (ASTNode) modifiedList.get(i); 166 ASTInsert object= getChangeProperty(curr); 167 if (object != null) { 168 RewriteEvent event= listEvent.insert(curr, i); 169 getRewriteEventStore().setEventEditGroup(event, object.description); 170 if (object.isBoundToPrevious) { 171 getRewriteEventStore().setInsertBoundToPrevious(curr); 172 } 173 } 174 } 175 } 176 177 private boolean isInsertBoundToPreviousByDefault(ASTNode node) { 178 return (node instanceof Statement || node instanceof FieldDeclaration); 179 } 180 181 184 public final void removeModifications() { 185 if (fHasASTModifications) { 186 getRootNode().accept(new ASTRewriteClear(this)); 187 fHasASTModifications= false; 188 } 189 fChangedProperties.clear(); 190 191 clearRewrite(); 192 } 193 194 public boolean hasASTModifications() { 195 return fHasASTModifications; 196 } 197 198 201 protected final void clearRewrite() { 202 getRewriteEventStore().clear(); 203 getNodeStore().clear(); 204 } 205 206 public final boolean isCollapsed(ASTNode node) { 207 return getNodeStore().isCollapsed(node); 208 } 209 210 211 217 public final void markAsInserted(ASTNode node, TextEditGroup description) { 218 Assert.isTrue(!isCollapsed(node), "Tries to insert a collapsed node"); ASTInsert insert= new ASTInsert(); 220 insert.isBoundToPrevious= isInsertBoundToPreviousByDefault(node); 221 insert.description= description; 222 setChangeProperty(node, insert); 223 fHasASTModifications= true; 224 node.setSourceRange(-1, 0); } 226 227 232 public final void markAsInserted(ASTNode node) { 233 markAsInserted(node, (TextEditGroup) null); 234 } 235 236 237 242 public final Block getCollapseTargetPlaceholder(Statement[] children) { 243 Block res= getNodeStore().createCollapsePlaceholder(); 244 List statements= res.statements(); 245 for (int i= 0; i < children.length; i++) { 246 statements.add(children[i]); 247 } 248 return res; 249 } 250 251 256 public final void markAsTracked(ASTNode node, TextEditGroup editGroup) { 257 if (getRewriteEventStore().getTrackedNodeData(node) != null) { 258 throw new IllegalArgumentException ("Node is already marked as tracked"); } 260 261 getRewriteEventStore().setTrackedNodeData(node, editGroup); 262 } 263 264 273 public final ASTNode collapseNodes(List list, int index, int length) { 274 Assert.isTrue(index >= 0 && length > 0 && list.size() >= (index + length), "Index or length out of bound"); 276 ASTNode firstNode= (ASTNode) list.get(index); 277 ASTNode lastNode= (ASTNode) list.get(index + length - 1); 278 validateIsInsideAST(firstNode); 279 validateIsInsideAST(lastNode); 280 281 Assert.isTrue(lastNode instanceof Statement, "Can only collapse statements"); 283 int startPos= firstNode.getStartPosition(); 284 int endPos= lastNode.getStartPosition() + lastNode.getLength(); 285 286 Block compoundNode= getNodeStore().createCollapsePlaceholder(); 287 List children= compoundNode.statements(); 288 compoundNode.setSourceRange(startPos, endPos - startPos); 289 290 StructuralPropertyDescriptor childProperty= firstNode.getLocationInParent(); 291 292 ListRewriteEvent existingEvent= getRewriteEventStore().getListEvent(firstNode.getParent(), childProperty, false); 293 if (existingEvent != null) { 294 RewriteEvent[] origChildren= existingEvent.getChildren(); 295 Assert.isTrue(origChildren.length == list.size()); 296 RewriteEvent[] newChildren= new RewriteEvent[origChildren.length - length + 1]; 297 System.arraycopy(origChildren, 0, newChildren, 0, index); 298 newChildren[index]= new NodeRewriteEvent(compoundNode, compoundNode); 299 System.arraycopy(origChildren, index + length, newChildren, index + 1, origChildren.length - index - length); 300 getRewriteEventStore().addEvent(firstNode.getParent(), childProperty, new ListRewriteEvent(newChildren)); 302 RewriteEvent[] newCollapsedChildren= new RewriteEvent[length]; 303 System.arraycopy(origChildren, index, newCollapsedChildren, 0, length); 304 getRewriteEventStore().addEvent(compoundNode, Block.STATEMENTS_PROPERTY, new ListRewriteEvent(newCollapsedChildren)); 305 } 306 307 for (int i= 0; i < length; i++) { 308 Object curr= list.remove(index); 309 children.add(curr); 310 } 311 list.add(index, compoundNode); 312 313 fHasASTModifications= true; 314 315 return compoundNode; 316 } 317 318 private final void validateIsInsideAST(ASTNode node) { 319 if (node.getStartPosition() == -1) { 320 throw new IllegalArgumentException ("Node is not an existing node"); } 322 323 if (node.getAST() != getAST()) { 324 throw new IllegalArgumentException ("Node is not inside the AST"); } 326 } 327 328 public final boolean isInserted(ASTNode node) { 329 return getChangeProperty(node) != null; 330 } 331 332 333 public boolean isRemoved(ASTNode node) { 334 return getRewriteEventStore().getChangeKind(node) == RewriteEvent.REMOVED; 335 } 336 337 public boolean isReplaced(ASTNode node) { 338 return getRewriteEventStore().getChangeKind(node) == RewriteEvent.REPLACED; 339 } 340 341 342 public final ASTNode getReplacingNode(ASTNode node) { 343 RewriteEvent event= getRewriteEventStore().findEvent(node, RewriteEventStore.ORIGINAL); 344 if (event != null && event.getChangeKind() == RewriteEvent.REPLACED) { 345 return (ASTNode) event.getNewValue(); 346 } 347 return null; 348 } 349 350 private final void setChangeProperty(ASTNode node, ASTInsert change) { 351 fChangedProperties.put(node, change); 352 } 353 354 private final ASTInsert getChangeProperty(ASTNode node) { 355 return (ASTInsert) fChangedProperties.get(node); 356 } 357 358 private static class ASTInsert { 359 public TextEditGroup description; 360 public boolean isBoundToPrevious; 361 } 362 363 } 364 | Popular Tags |