EclipseJDT Source Viewer

Home|eclipse_jdt/src/org/eclipse/jdt/core/dom/InternalASTRewrite.java
1/*******************************************************************************
2 * Copyright (c) 2004, 2013 IBM Corporation and others.
3 *
4 * This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
8 *
9 * SPDX-License-Identifier: EPL-2.0
10 *
11 * Contributors:
12 *     IBM Corporation - initial API and implementation
13 *******************************************************************************/
14package org.eclipse.jdt.core.dom;
15import java.util.Hashtable;
16import java.util.List;
17import java.util.Map;
18
19import org.eclipse.text.edits.MultiTextEdit;
20import org.eclipse.text.edits.TextEdit;
21
22import org.eclipse.jface.text.IDocument;
23import org.eclipse.jface.text.TextUtilities;
24
25import org.eclipse.jdt.core.JavaCore;
26import org.eclipse.jdt.core.dom.rewrite.TargetSourceRangeComputer;
27import org.eclipse.jdt.internal.compiler.parser.RecoveryScannerData;
28import org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer;
29import org.eclipse.jdt.internal.core.dom.rewrite.LineInformation;
30import org.eclipse.jdt.internal.core.dom.rewrite.ListRewriteEvent;
31import org.eclipse.jdt.internal.core.dom.rewrite.NodeInfoStore;
32import org.eclipse.jdt.internal.core.dom.rewrite.NodeRewriteEvent;
33import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore;
34import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore.CopySourceInfo;
35import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore.PropertyLocation;
36
37/**
38 * Internal class: not intended to be used by client.
39 * When AST modifications recording is enabled, all changes are recorded by this class.
40 */
41@SuppressWarnings({"rawtypes""unchecked"})
42class InternalASTRewrite extends NodeEventHandler {
43
44    /** root node for the rewrite: Only nodes under this root are accepted */
45    private CompilationUnit root;
46
47    protected final RewriteEventStore eventStore;
48    protected final NodeInfoStore nodeStore;
49    /** ASTNode clone -> ASTNode original */
50    protected final Hashtable clonedNodes;
51
52    int cloneDepth = 0;
53
54    /**
55     * Constructor
56     * @param root root node of the recorded ast.
57     */
58    public InternalASTRewrite(CompilationUnit root) {
59        this.root = root;
60        this.eventStore = new RewriteEventStore();
61        this.nodeStore = new NodeInfoStore(root.getAST());
62        this.clonedNodes = new Hashtable();
63    }
64
65    /**
66     * Performs the rewrite: The rewrite events are translated to the corresponding in text changes.
67     * The given options can be null in which case the global options {@link JavaCore#getOptions() JavaCore.getOptions()}
68     * will be used.
69     *
70     * @param document Document which describes the code of the AST that is passed in in the
71     * constructor. This document is accessed read-only.
72     * @param options the given options
73     * @throws IllegalArgumentException if the rewrite fails
74     * @return Returns the edit describing the text changes.
75     */
76    public TextEdit rewriteAST(IDocument documentMap options) {
77        TextEdit result = new MultiTextEdit();
78
79        final CompilationUnit rootNode = getRootNode();
80        if (rootNode != null) {
81            TargetSourceRangeComputer xsrComputer = new TargetSourceRangeComputer() {
82                /**
83                 * This implementation of
84                 * {@link TargetSourceRangeComputer#computeSourceRange(ASTNode)}
85                 * is specialized to work in the case of internal AST rewriting, where the
86                 * original AST has been modified from its original form. This means that
87                 * one cannot trust that the root of the given node is the compilation unit.
88                 */
89                @Override
90                public SourceRange computeSourceRange(ASTNode node) {
91                    int extendedStartPosition = rootNode.getExtendedStartPosition(node);
92                    int extendedLength = rootNode.getExtendedLength(node);
93                    return new SourceRange(extendedStartPositionextendedLength);
94                }
95            };
96            char[] contentdocument.get().toCharArray();
97            LineInformation lineInfoLineInformation.create(document);
98            String lineDelimTextUtilities.getDefaultLineDelimiter(document);
99            List commentsrootNode.getCommentList();
100
101            Map currentOptions = options == null ? JavaCore.getOptions() : options;
102            ASTRewriteAnalyzer visitor = new ASTRewriteAnalyzer(contentlineInfolineDelimresult, this.eventStore, this.nodeStorecommentscurrentOptionsxsrComputer, (RecoveryScannerData)rootNode.getStatementsRecoveryData());
103            rootNode.accept(visitor);
104        }
105        return result;
106    }
107
108    private  void markAsMoveOrCopyTarget(ASTNode nodeASTNode newChild) {
109        if (this.cloneDepth == 0) {
110            while (node != null && this.clonedNodes.containsKey(node)) {
111                /*
112                 * A modified node cannot be considered as cloned any more.
113                 * we can't copy the original formatting/comments and at the same time modify the node.
114                 *
115                 * Workaround for https://bugs.eclipse.org/405699 is to remove such nodes from clonedNodes
116                 * and instead mark all children as cloned (or skip them if they are not in clonedNodes).
117                 */
118                ASTNode orig = (ASTNode) this.clonedNodes.remove(node);
119                if (orig != null) {
120                    List properties = node.structuralPropertiesForType();
121                    for (int i0i < properties.size(); i++) {
122                        StructuralPropertyDescriptor property = (StructuralPropertyDescriptorproperties.get(i);
123                        Object child = node.getStructuralProperty(property);
124                        if (child instanceof ASTNode) {
125                            markAsMoveOrCopyTarget(node, (ASTNodechild);
126                        } else if (child instanceof List) {
127                            List children = (Listchild;
128                            for (int j0j < children.size(); j++) {
129                                ASTNode clonedChild = (ASTNodechildren.get(j);
130                                markAsMoveOrCopyTarget(nodeclonedChild);
131                            }
132                        }
133                    }
134                }
135
136                node = node.getParent();
137            }
138        }
139
140        ASTNode source = (ASTNode)this.clonedNodes.get(newChild);
141        if(source != null) {
142            if(this.cloneDepth == 0) {
143                PropertyLocation propertyLocation = this.eventStore.getPropertyLocation(sourceRewriteEventStore.ORIGINAL);
144                CopySourceInfo sourceInfo =
145                    this.eventStore.markAsCopySource(
146                        propertyLocation.getParent(),
147                        propertyLocation.getProperty(),
148                        source,
149                        false);
150                this.nodeStore.markAsCopyTarget(newChildsourceInfo);
151            }
152        } else if((newChild.getFlags() & ASTNode.ORIGINAL) != 0) {
153            PropertyLocation propertyLocation = this.eventStore.getPropertyLocation(newChildRewriteEventStore.ORIGINAL);
154            CopySourceInfo sourceInfo =
155                this.eventStore.markAsCopySource(
156                    propertyLocation.getParent(),
157                    propertyLocation.getProperty(),
158                    newChild,
159                    true);
160            this.nodeStore.markAsCopyTarget(newChildsourceInfo);
161        }
162    }
163
164    private CompilationUnit getRootNode() {
165        return this.root;
166    }
167
168    @Override
169    public String toString() {
170        StringBuilder buf = new StringBuilder();
171        buf.append("Events:\n"); //$NON-NLS-1$
172        buf.append(this.eventStore.toString());
173        return buf.toString();
174    }
175
176    @Override
177    void preValueChangeEvent(ASTNode nodeSimplePropertyDescriptor property) {
178        // force event creation
179        getNodeEvent(nodeproperty);
180    }
181
182    @Override
183    void postValueChangeEvent(ASTNode nodeSimplePropertyDescriptor property) {
184        NodeRewriteEvent event = getNodeEvent(nodeproperty);
185        event.setNewValue(node.getStructuralProperty(property));
186    }
187
188    @Override
189    void preAddChildEvent(ASTNode nodeASTNode child,    StructuralPropertyDescriptor property) {
190        if(property.isChildProperty()) {
191            NodeRewriteEvent event = getNodeEvent(nodeproperty);
192            event.setNewValue(child);
193            if(child != null) {
194                markAsMoveOrCopyTarget(nodechild);
195            }
196        } else if(property.isChildListProperty()) {
197            // force event creation
198            getListEvent(nodeproperty);
199        }
200    }
201
202    @Override
203    void postAddChildEvent(ASTNode nodeASTNode child,    StructuralPropertyDescriptor property) {
204        if(property.isChildListProperty()) {
205
206            ListRewriteEvent event = getListEvent(nodeproperty);
207            List list = (List)node.getStructuralProperty(property);
208            int i = list.indexOf(child);
209            int s = list.size();
210            int index;
211            if(i + 1 < s) {
212                ASTNode nextNode = (ASTNode)list.get(i + 1);
213                index = event.getIndex(nextNodeListRewriteEvent.NEW);
214            } else {
215                index = -1;
216            }
217            event.insert(childindex);
218            if(child != null) {
219                markAsMoveOrCopyTarget(nodechild);
220            }
221        }
222    }
223
224    @Override
225    void preRemoveChildEvent(ASTNode nodeASTNode childStructuralPropertyDescriptor property) {
226        if(property.isChildProperty()) {
227            NodeRewriteEvent event = getNodeEvent(nodeproperty);
228            event.setNewValue(null);
229        } else if(property.isChildListProperty()) {
230            ListRewriteEvent event = getListEvent(nodeproperty);
231            int i = event.getIndex(childListRewriteEvent.NEW);
232            NodeRewriteEvent nodeEvent = (NodeRewriteEvent)event.getChildren()[i];
233            if(nodeEvent.getOriginalValue() == null) {
234                event.revertChange(nodeEvent);
235            } else {
236                nodeEvent.setNewValue(null);
237            }
238        }
239    }
240
241    @Override
242    void preReplaceChildEvent(ASTNode nodeASTNode childASTNode newChildStructuralPropertyDescriptor property) {
243        if(property.isChildProperty()) {
244            NodeRewriteEvent event = getNodeEvent(nodeproperty);
245            event.setNewValue(newChild);
246            if(newChild != null) {
247                markAsMoveOrCopyTarget(nodenewChild);
248            }
249        } else if(property.isChildListProperty()) {
250            ListRewriteEvent event = getListEvent(nodeproperty);
251            int i = event.getIndex(childListRewriteEvent.NEW);
252            NodeRewriteEvent nodeEvent = (NodeRewriteEvent)event.getChildren()[i];
253            nodeEvent.setNewValue(newChild);
254            if(newChild != null) {
255                markAsMoveOrCopyTarget(nodenewChild);
256            }
257        }
258    }
259
260
261    @Override
262    void preCloneNodeEvent(ASTNode node) {
263        this.cloneDepth++;
264    }
265
266
267    @Override
268    void postCloneNodeEvent(ASTNode nodeASTNode clone) {
269        if(node.ast == this.root.ast && clone.ast == this.root.ast) {
270            if((node.getFlags() & ASTNode.ORIGINAL) != 0) {
271                this.clonedNodes.put(clonenode);
272            } else {
273                // node can be a cloned node
274                Object original = this.clonedNodes.get(node);
275                if(original != null) {
276                    this.clonedNodes.put(cloneoriginal);
277                }
278            }
279        }
280        this.cloneDepth--;
281    }
282
283    private NodeRewriteEvent getNodeEvent(ASTNode nodeStructuralPropertyDescriptor property) {
284        return this.eventStore.getNodeEvent(nodepropertytrue);
285    }
286
287    private ListRewriteEvent getListEvent(ASTNode nodeStructuralPropertyDescriptor property) {
288        return this.eventStore.getListEvent(nodepropertytrue);
289    }
290}
291
MembersX
InternalASTRewrite:preAddChildEvent
InternalASTRewrite:preRemoveChildEvent:Block:Block:event
InternalASTRewrite:preReplaceChildEvent:Block:Block:i
InternalASTRewrite:rewriteAST:Block:Block:comments
InternalASTRewrite:markAsMoveOrCopyTarget:Block:Block:Block:propertyLocation
InternalASTRewrite:markAsMoveOrCopyTarget:Block:Block:Block:sourceInfo
InternalASTRewrite:preReplaceChildEvent:Block:Block:nodeEvent
InternalASTRewrite:getListEvent
InternalASTRewrite:preRemoveChildEvent:Block:Block:i
InternalASTRewrite:preReplaceChildEvent
InternalASTRewrite:postAddChildEvent:Block:Block:index
InternalASTRewrite:rewriteAST
InternalASTRewrite:postCloneNodeEvent:Block:Block:Block:original
InternalASTRewrite:postAddChildEvent:Block:Block:event
InternalASTRewrite:postAddChildEvent:Block:Block:list
InternalASTRewrite:markAsMoveOrCopyTarget
InternalASTRewrite:preReplaceChildEvent:Block:Block:event
InternalASTRewrite:getNodeEvent
InternalASTRewrite:preValueChangeEvent
InternalASTRewrite:rewriteAST:Block:Block:xsrComputer
InternalASTRewrite:postAddChildEvent:Block:Block:s
InternalASTRewrite:markAsMoveOrCopyTarget:Block:Block:Block:Block:properties
InternalASTRewrite:postAddChildEvent:Block:Block:Block:nextNode
InternalASTRewrite:rewriteAST:Block:Block:computeSourceRange:Block:extendedLength
InternalASTRewrite:rewriteAST:Block:result
InternalASTRewrite:postAddChildEvent
InternalASTRewrite:eventStore
InternalASTRewrite:rewriteAST:Block:rootNode
InternalASTRewrite:rewriteAST:Block:Block:computeSourceRange:Block:extendedStartPosition
InternalASTRewrite:rewriteAST:Block:Block:content
InternalASTRewrite:postCloneNodeEvent
InternalASTRewrite:markAsMoveOrCopyTarget:Block:Block:Block:Block:Block:Block:children
InternalASTRewrite:clonedNodes
InternalASTRewrite:preRemoveChildEvent:Block:Block:nodeEvent
InternalASTRewrite:rewriteAST:Block:Block:visitor
InternalASTRewrite:markAsMoveOrCopyTarget:Block:Block:Block:Block:Block:child
InternalASTRewrite:postValueChangeEvent
InternalASTRewrite:markAsMoveOrCopyTarget:Block:Block:propertyLocation
InternalASTRewrite:nodeStore
InternalASTRewrite:toString
InternalASTRewrite:cloneDepth
InternalASTRewrite:InternalASTRewrite
InternalASTRewrite:postAddChildEvent:Block:Block:i
InternalASTRewrite:rewriteAST:Block:Block:currentOptions
InternalASTRewrite:markAsMoveOrCopyTarget:Block:source
InternalASTRewrite:getRootNode
InternalASTRewrite:preCloneNodeEvent
InternalASTRewrite:markAsMoveOrCopyTarget:Block:Block:Block:Block:Block:Block:Block:clonedChild
InternalASTRewrite:rewriteAST:Block:Block:computeSourceRange
InternalASTRewrite:preAddChildEvent:Block:Block:event
InternalASTRewrite:rewriteAST:Block:Block:lineDelim
InternalASTRewrite:preRemoveChildEvent
InternalASTRewrite:rewriteAST:Block:Block:lineInfo
InternalASTRewrite:markAsMoveOrCopyTarget:Block:Block:Block:Block:Block:property
InternalASTRewrite:postValueChangeEvent:Block:event
InternalASTRewrite:toString:Block:buf
InternalASTRewrite:markAsMoveOrCopyTarget:Block:Block:Block:orig
InternalASTRewrite:root
InternalASTRewrite:markAsMoveOrCopyTarget:Block:Block:sourceInfo
Members
X