KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > structure > CompilationUnitRewrite


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.corext.refactoring.structure;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Iterator JavaDoc;
15 import java.util.List JavaDoc;
16
17 import org.eclipse.text.edits.MultiTextEdit;
18 import org.eclipse.text.edits.TextEdit;
19 import org.eclipse.text.edits.TextEditGroup;
20
21 import org.eclipse.core.runtime.CoreException;
22 import org.eclipse.core.runtime.IProgressMonitor;
23
24 import org.eclipse.jface.text.Document;
25 import org.eclipse.jface.text.IDocument;
26
27 import org.eclipse.ltk.core.refactoring.CategorizedTextEditGroup;
28 import org.eclipse.ltk.core.refactoring.GroupCategorySet;
29
30 import org.eclipse.jdt.core.ICompilationUnit;
31 import org.eclipse.jdt.core.JavaModelException;
32 import org.eclipse.jdt.core.WorkingCopyOwner;
33 import org.eclipse.jdt.core.dom.AST;
34 import org.eclipse.jdt.core.dom.CompilationUnit;
35 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
36 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
37
38 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
39 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
40 import org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange;
41 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
42
43 import org.eclipse.jdt.internal.ui.JavaPlugin;
44
45 /**
46  * A {@link CompilationUnitRewrite} holds all data structures that are typically
47  * required for non-trivial refactorings. All getters are initialized lazily to
48  * avoid lengthy processing in
49  * {@link org.eclipse.ltk.core.refactoring.Refactoring#checkInitialConditions(org.eclipse.core.runtime.IProgressMonitor)}.
50  * <p>
51  * Bindings are resolved by default, but can be disabled with <code>setResolveBindings(false)</code>.
52  * Bindings recovery is disabled by default, but can be enabled with <code>setBindingRecovery(true)</code>.
53  * Statements recovery is enabled by default, but can be disabled with <code>setStatementsRecovery(false)</code>.
54  * </p>
55  */

56 public class CompilationUnitRewrite {
57     //TODO: add RefactoringStatus fStatus;?
58
private ICompilationUnit fCu;
59     private List JavaDoc/*<TextEditGroup>*/ fTextEditGroups= new ArrayList JavaDoc();
60     
61     private CompilationUnit fRoot; // lazily initialized
62
private ASTRewrite fRewrite; // lazily initialized
63
private ImportRewrite fImportRewrite; // lazily initialized
64
private ImportRemover fImportRemover; // lazily initialized
65
private boolean fResolveBindings= true;
66     private boolean fStatementsRecovery= true;
67     private boolean fBindingsRecovery= false;
68     private final WorkingCopyOwner fOwner;
69     private IDocument fRememberContent= null;
70
71     
72     public CompilationUnitRewrite(ICompilationUnit cu) {
73         this(null, cu, null);
74     }
75
76     public CompilationUnitRewrite(WorkingCopyOwner owner, ICompilationUnit cu) {
77         this(owner, cu, null);
78     }
79
80     public CompilationUnitRewrite(ICompilationUnit cu, CompilationUnit root) {
81         this(null, cu, root);
82     }
83
84     public CompilationUnitRewrite(WorkingCopyOwner owner, ICompilationUnit cu, CompilationUnit root) {
85         fOwner= owner;
86         fCu= cu;
87         fRoot= root;
88     }
89     
90     public void rememberContent() {
91         fRememberContent= new Document();
92     }
93     
94
95     /**
96      * Controls whether the compiler should provide binding information for the AST
97      * nodes it creates. To be effective, this method must be called before any
98      * of {@link #getRoot()},{@link #getASTRewrite()},
99      * {@link #getImportRemover()}. This method has no effect if the target object
100      * has been created with {@link #CompilationUnitRewrite(ICompilationUnit, CompilationUnit)}.
101      * <p>
102      * Defaults to <b><code>true</code></b> (do resolve bindings).
103      * </p>
104      *
105      * @param resolve
106      * <code>true</code> if bindings are wanted, and
107      * <code>false</code> if bindings are not of interest
108      * @see org.eclipse.jdt.core.dom.ASTParser#setResolveBindings(boolean)
109      * Note: The default value (<code>true</code>) differs from the one of
110      * the corresponding method in ASTParser.
111      */

112     public void setResolveBindings(boolean resolve) {
113         fResolveBindings= resolve;
114     }
115     
116     /**
117      * Controls whether the compiler should perform statements recovery.
118      * To be effective, this method must be called before any
119      * of {@link #getRoot()},{@link #getASTRewrite()},
120      * {@link #getImportRemover()}. This method has no effect if the target object
121      * has been created with {@link #CompilationUnitRewrite(ICompilationUnit, CompilationUnit)}.
122      * <p>
123      * Defaults to <b><code>true</code></b> (do perform statements recovery).
124      * </p>
125      *
126      * @param statementsRecovery whether statements recovery should be performed
127      * @see org.eclipse.jdt.core.dom.ASTParser#setStatementsRecovery(boolean)
128      */

129     public void setStatementsRecovery(boolean statementsRecovery) {
130         fStatementsRecovery= statementsRecovery;
131     }
132     
133     /**
134      * Controls whether the compiler should perform bindings recovery.
135      * To be effective, this method must be called before any
136      * of {@link #getRoot()},{@link #getASTRewrite()},
137      * {@link #getImportRemover()}. This method has no effect if the target object
138      * has been created with {@link #CompilationUnitRewrite(ICompilationUnit, CompilationUnit)}.
139      * <p>
140      * Defaults to <b><code>false</code></b> (do not perform bindings recovery).
141      * </p>
142      *
143      * @param bindingsRecovery whether bindings recovery should be performed
144      * @see org.eclipse.jdt.core.dom.ASTParser#setBindingsRecovery(boolean)
145      */

146     public void setBindingRecovery(boolean bindingsRecovery) {
147         fBindingsRecovery= bindingsRecovery;
148     }
149     
150     public void clearASTRewrite() {
151         fRewrite= null;
152         fTextEditGroups= new ArrayList JavaDoc();
153     }
154
155     public void clearImportRewrites() {
156         fImportRewrite= null;
157     }
158
159     public void clearASTAndImportRewrites() {
160         clearASTRewrite();
161         fImportRewrite= null;
162     }
163
164     public CategorizedTextEditGroup createCategorizedGroupDescription(String JavaDoc name, GroupCategorySet set) {
165         CategorizedTextEditGroup result= new CategorizedTextEditGroup(name, set);
166         fTextEditGroups.add(result);
167         return result;
168     }
169
170     public TextEditGroup createGroupDescription(String JavaDoc name) {
171         TextEditGroup result= new TextEditGroup(name);
172         fTextEditGroups.add(result);
173         return result;
174     }
175     
176
177     public CompilationUnitChange createChange() throws CoreException {
178         return createChange(true, null);
179     }
180     
181     /**
182      * Creates a compilation unit change based on the events recorded by this compilation unit rewrite.
183      * @param generateGroups <code>true</code> to generate text edit groups, <code>false</code> otherwise
184      * @param monitor the progress monitor or <code>null</code>
185      * @return a {@link CompilationUnitChange}, or <code>null</code> for an empty change
186      * @throws CoreException when text buffer acquisition or import rewrite text edit creation fails
187      * @throws IllegalArgumentException when the AST rewrite encounters problems
188      */

189     public CompilationUnitChange createChange(boolean generateGroups, IProgressMonitor monitor) throws CoreException {
190         return createChange(fCu.getElementName(), generateGroups, monitor);
191     }
192     
193     /**
194      * Creates a compilation unit change based on the events recorded by this compilation unit rewrite.
195      * @param name the name of the change to create
196      * @param generateGroups <code>true</code> to generate text edit groups, <code>false</code> otherwise
197      * @param monitor the progress monitor or <code>null</code>
198      * @return a {@link CompilationUnitChange}, or <code>null</code> for an empty change
199      * @throws CoreException when text buffer acquisition or import rewrite text edit creation fails
200      * @throws IllegalArgumentException when the AST rewrite encounters problems
201      */

202     public CompilationUnitChange createChange(String JavaDoc name, boolean generateGroups, IProgressMonitor monitor) throws CoreException {
203         CompilationUnitChange cuChange= new CompilationUnitChange(name, fCu);
204         MultiTextEdit multiEdit= new MultiTextEdit();
205         cuChange.setEdit(multiEdit);
206         return attachChange(cuChange, generateGroups, monitor);
207     }
208     
209     
210     /**
211      * Attaches the changes of this compilation unit rewrite to the given CU Change. The given
212      * change <b>must</b> either have no root edit, or a MultiTextEdit as a root edit.
213      * The edits in the given change <b>must not</b> overlap with the changes of
214      * this compilation unit.
215      *
216      * @param cuChange existing CompilationUnitChange with a MultiTextEdit root or no root at all.
217      * @param generateGroups <code>true</code> to generate text edit groups, <code>false</code> otherwise
218      * @param monitor the progress monitor or <code>null</code>
219      * @return a change combining the changes of this rewrite and the given rewrite.
220      * @throws CoreException
221      */

222     public CompilationUnitChange attachChange(CompilationUnitChange cuChange, boolean generateGroups, IProgressMonitor monitor) throws CoreException {
223         try {
224             boolean needsAstRewrite= fRewrite != null; // TODO: do we need something like ASTRewrite#hasChanges() here?
225
boolean needsImportRemoval= fImportRemover != null && fImportRemover.hasRemovedNodes();
226             boolean needsImportRewrite= fImportRewrite != null && fImportRewrite.hasRecordedChanges() || needsImportRemoval;
227             if (!needsAstRewrite && !needsImportRemoval && !needsImportRewrite)
228                 return null;
229                         
230             MultiTextEdit multiEdit= (MultiTextEdit) cuChange.getEdit();
231             if (multiEdit == null) {
232                 multiEdit= new MultiTextEdit();
233                 cuChange.setEdit(multiEdit);
234             }
235                 
236             if (needsAstRewrite) {
237                 TextEdit rewriteEdit;
238                 if (fRememberContent != null) {
239                     rewriteEdit= fRewrite.rewriteAST(fRememberContent, fCu.getJavaProject().getOptions(true));
240                 } else {
241                     rewriteEdit= fRewrite.rewriteAST();
242                 }
243                 if (!isEmptyEdit(rewriteEdit)) {
244                     multiEdit.addChild(rewriteEdit);
245                     if (generateGroups) {
246                         for (Iterator JavaDoc iter= fTextEditGroups.iterator(); iter.hasNext();) {
247                             TextEditGroup group= (TextEditGroup) iter.next();
248                             cuChange.addTextEditGroup(group);
249                         }
250                     }
251                 }
252             }
253             if (needsImportRemoval) {
254                 fImportRemover.applyRemoves(getImportRewrite());
255             }
256             if (needsImportRewrite) {
257                 TextEdit importsEdit= fImportRewrite.rewriteImports(monitor);
258                 if (!isEmptyEdit(importsEdit)) {
259                     multiEdit.addChild(importsEdit);
260                     String JavaDoc importUpdateName= RefactoringCoreMessages.ASTData_update_imports;
261                     cuChange.addTextEditGroup(new TextEditGroup(importUpdateName, importsEdit));
262                 }
263             } else {
264                 
265             }
266             if (isEmptyEdit(multiEdit))
267                 return null;
268             return cuChange;
269         } finally {
270             if (monitor != null)
271                 monitor.done();
272         }
273     }
274
275     private static boolean isEmptyEdit(TextEdit edit) {
276         return edit.getClass() == MultiTextEdit.class && ! edit.hasChildren();
277     }
278     
279     public ICompilationUnit getCu() {
280         return fCu;
281     }
282
283     public CompilationUnit getRoot() {
284         if (fRoot == null)
285             fRoot= new RefactoringASTParser(AST.JLS3).parse(fCu, fOwner, fResolveBindings, fStatementsRecovery, fBindingsRecovery, null);
286         return fRoot;
287     }
288     
289     public AST getAST() {
290         return getRoot().getAST();
291     }
292
293     public ASTRewrite getASTRewrite() {
294         if (fRewrite == null) {
295             fRewrite= ASTRewrite.create(getRoot().getAST());
296             if (fRememberContent != null) { // wain until ast rewrite is accessed first
297
try {
298                     fRememberContent.set(fCu.getSource());
299                 } catch (JavaModelException e) {
300                     fRememberContent= null;
301                 }
302             }
303         }
304         return fRewrite;
305     }
306
307     public ImportRewrite getImportRewrite() {
308         if (fImportRewrite == null) {
309             // lazily initialized to avoid lengthy processing in checkInitialConditions(..)
310
try {
311                 if (fRoot == null) {
312                     fImportRewrite= StubUtility.createImportRewrite(fCu, true);
313                 } else {
314                     fImportRewrite= StubUtility.createImportRewrite(getRoot(), true);
315                 }
316             } catch (CoreException e) {
317                 JavaPlugin.log(e);
318                 throw new IllegalStateException JavaDoc(e.getMessage()); // like ASTParser#createAST(..) does
319
}
320         }
321         return fImportRewrite;
322         
323     }
324     
325     public ImportRemover getImportRemover() {
326         if (fImportRemover == null) {
327             fImportRemover= new ImportRemover(fCu.getJavaProject(), getRoot());
328         }
329         return fImportRemover;
330     }
331 }
332
Popular Tags