]> git.uio.no Git - ifi-stolz-refaktor.git/blame - case-study/jdt-before/core refactoring/org/eclipse/jdt/internal/corext/refactoring/structure/CompilationUnitRewrite.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-before / core refactoring / org / eclipse / jdt / internal / corext / refactoring / structure / CompilationUnitRewrite.java
CommitLineData
1b2798f6
EK
1/*******************************************************************************
2 * Copyright (c) 2000, 2011 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 *******************************************************************************/
11package org.eclipse.jdt.internal.corext.refactoring.structure;
12
13import java.util.ArrayList;
14import java.util.Iterator;
15import java.util.List;
16
17import org.eclipse.core.runtime.CoreException;
18import org.eclipse.core.runtime.IProgressMonitor;
19
20import org.eclipse.text.edits.MultiTextEdit;
21import org.eclipse.text.edits.TextEdit;
22import org.eclipse.text.edits.TextEditGroup;
23
24import org.eclipse.jface.text.Document;
25import org.eclipse.jface.text.IDocument;
26
27import org.eclipse.ltk.core.refactoring.CategorizedTextEditGroup;
28import org.eclipse.ltk.core.refactoring.GroupCategorySet;
29
30import org.eclipse.jdt.core.ICompilationUnit;
31import org.eclipse.jdt.core.JavaModelException;
32import org.eclipse.jdt.core.WorkingCopyOwner;
33import org.eclipse.jdt.core.dom.AST;
34import org.eclipse.jdt.core.dom.CompilationUnit;
35import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
36import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
37import org.eclipse.jdt.core.refactoring.CompilationUnitChange;
38
39import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
40import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
41import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
42
43import org.eclipse.jdt.internal.ui.JavaPlugin;
44import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider;
45
46/**
47 * A {@link CompilationUnitRewrite} holds all data structures that are typically
48 * required for non-trivial refactorings. All getters are initialized lazily to
49 * avoid lengthy processing in
50 * {@link org.eclipse.ltk.core.refactoring.Refactoring#checkInitialConditions(org.eclipse.core.runtime.IProgressMonitor)}.
51 * <p>
52 * Bindings are resolved by default, but can be disabled with <code>setResolveBindings(false)</code>.
53 * Statements recovery is enabled by default, but can be disabled with <code>setStatementsRecovery(false)</code>.
54 * Bindings recovery is disabled by default, but can be enabled with <code>setBindingRecovery(true)</code>.
55 * </p>
56 */
57public class CompilationUnitRewrite {
58 //TODO: add RefactoringStatus fStatus;?
59 private ICompilationUnit fCu;
60 private List<TextEditGroup> fTextEditGroups= new ArrayList<TextEditGroup>();
61
62 private CompilationUnit fRoot; // lazily initialized
63 private ASTRewrite fRewrite; // lazily initialized
64 private ImportRewrite fImportRewrite; // lazily initialized
65 private ImportRemover fImportRemover; // lazily initialized
66 private boolean fResolveBindings= true;
67 private boolean fStatementsRecovery= true;
68 private boolean fBindingsRecovery= false;
69 private final WorkingCopyOwner fOwner;
70 private IDocument fRememberContent= null;
71
72
73 public CompilationUnitRewrite(ICompilationUnit cu) {
74 this(null, cu, null);
75 }
76
77 public CompilationUnitRewrite(WorkingCopyOwner owner, ICompilationUnit cu) {
78 this(owner, cu, null);
79 }
80
81 public CompilationUnitRewrite(ICompilationUnit cu, CompilationUnit root) {
82 this(null, cu, root);
83 }
84
85 public CompilationUnitRewrite(WorkingCopyOwner owner, ICompilationUnit cu, CompilationUnit root) {
86 fOwner= owner;
87 fCu= cu;
88 fRoot= root;
89 }
90
91 public void rememberContent() {
92 fRememberContent= new Document();
93 }
94
95
96 /**
97 * Controls whether the compiler should provide binding information for the AST
98 * nodes it creates. To be effective, this method must be called before any
99 * of {@link #getRoot()},{@link #getASTRewrite()},
100 * {@link #getImportRemover()}. This method has no effect if the target object
101 * has been created with {@link #CompilationUnitRewrite(ICompilationUnit, CompilationUnit)}.
102 * <p>
103 * Defaults to <b><code>true</code></b> (do resolve bindings).
104 * </p>
105 *
106 * @param resolve
107 * <code>true</code> if bindings are wanted, and
108 * <code>false</code> if bindings are not of interest
109 * @see org.eclipse.jdt.core.dom.ASTParser#setResolveBindings(boolean)
110 * Note: The default value (<code>true</code>) differs from the one of
111 * the corresponding method in ASTParser.
112 */
113 public void setResolveBindings(boolean resolve) {
114 fResolveBindings= resolve;
115 }
116
117 /**
118 * Controls whether the compiler should perform statements recovery.
119 * To be effective, this method must be called before any
120 * of {@link #getRoot()},{@link #getASTRewrite()},
121 * {@link #getImportRemover()}. This method has no effect if the target object
122 * has been created with {@link #CompilationUnitRewrite(ICompilationUnit, CompilationUnit)}.
123 * <p>
124 * Defaults to <b><code>true</code></b> (do perform statements recovery).
125 * </p>
126 *
127 * @param statementsRecovery whether statements recovery should be performed
128 * @see org.eclipse.jdt.core.dom.ASTParser#setStatementsRecovery(boolean)
129 */
130 public void setStatementsRecovery(boolean statementsRecovery) {
131 fStatementsRecovery= statementsRecovery;
132 }
133
134 /**
135 * Controls whether the compiler should perform bindings recovery.
136 * To be effective, this method must be called before any
137 * of {@link #getRoot()},{@link #getASTRewrite()},
138 * {@link #getImportRemover()}. This method has no effect if the target object
139 * has been created with {@link #CompilationUnitRewrite(ICompilationUnit, CompilationUnit)}.
140 * <p>
141 * Defaults to <b><code>false</code></b> (do not perform bindings recovery).
142 * </p>
143 *
144 * @param bindingsRecovery whether bindings recovery should be performed
145 * @see org.eclipse.jdt.core.dom.ASTParser#setBindingsRecovery(boolean)
146 */
147 public void setBindingRecovery(boolean bindingsRecovery) {
148 fBindingsRecovery= bindingsRecovery;
149 }
150
151 public void clearASTRewrite() {
152 fRewrite= null;
153 fTextEditGroups= new ArrayList<TextEditGroup>();
154 }
155
156 public void clearImportRewrites() {
157 fImportRewrite= null;
158 }
159
160 public void clearASTAndImportRewrites() {
161 clearASTRewrite();
162 fImportRewrite= null;
163 }
164
165 public CategorizedTextEditGroup createCategorizedGroupDescription(String name, GroupCategorySet set) {
166 CategorizedTextEditGroup result= new CategorizedTextEditGroup(name, set);
167 fTextEditGroups.add(result);
168 return result;
169 }
170
171 public TextEditGroup createGroupDescription(String name) {
172 TextEditGroup result= new TextEditGroup(name);
173 fTextEditGroups.add(result);
174 return result;
175 }
176
177 /**
178 * Creates a compilation unit change based on the events recorded by this compilation unit
179 * rewrite.
180 *
181 * @param generateGroups <code>true</code> to generate text edit groups, <code>false</code> otherwise
182 * @return a {@link CompilationUnitChange}, or <code>null</code> for an empty change
183 * @throws CoreException when text buffer acquisition or import rewrite text edit creation fails
184 * @throws IllegalArgumentException when the AST rewrite encounters problems
185 * @since 3.6
186 */
187 public CompilationUnitChange createChange(boolean generateGroups) throws CoreException {
188 return createChange(generateGroups, null);
189 }
190
191 /**
192 * Creates a compilation unit change based on the events recorded by this compilation unit
193 * rewrite.
194 * <p>
195 * DO NOT REMOVE, used in a product.</p>
196 *
197 * @return a {@link org.eclipse.jdt.core.refactoring.CompilationUnitChange}, or <code>null</code> for an empty change
198 * @throws CoreException when text buffer acquisition or import rewrite text edit creation fails
199 * @throws IllegalArgumentException when the AST rewrite encounters problems
200 * @deprecated since 3.5, replaced by {@link #createChange(boolean)}
201 */
202 public org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange createChange() throws CoreException {
203 CompilationUnitChange change= createChange(true);
204 if (change == null)
205 return null;
206 return new org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange(change);
207 }
208
209 /**
210 * Creates a compilation unit change based on the events recorded by this compilation unit
211 * rewrite.
212 *
213 * @param generateGroups <code>true</code> to generate text edit groups, <code>false</code>
214 * otherwise
215 * @param monitor the progress monitor or <code>null</code>
216 * @return a {@link CompilationUnitChange}, or <code>null</code> for an empty change
217 * @throws CoreException when text buffer acquisition or import rewrite text edit creation fails
218 * @throws IllegalArgumentException when the AST rewrite encounters problems
219 */
220 public CompilationUnitChange createChange(boolean generateGroups, IProgressMonitor monitor) throws CoreException {
221 return createChange(fCu.getElementName(), generateGroups, monitor);
222 }
223
224 /**
225 * Creates a compilation unit change based on the events recorded by this compilation unit rewrite.
226 * @param name the name of the change to create
227 * @param generateGroups <code>true</code> to generate text edit groups, <code>false</code> otherwise
228 * @param monitor the progress monitor or <code>null</code>
229 * @return a {@link CompilationUnitChange}, or <code>null</code> for an empty change
230 * @throws CoreException when text buffer acquisition or import rewrite text edit creation fails
231 * @throws IllegalArgumentException when the AST rewrite encounters problems
232 */
233 public CompilationUnitChange createChange(String name, boolean generateGroups, IProgressMonitor monitor) throws CoreException {
234 CompilationUnitChange cuChange= new CompilationUnitChange(name, fCu);
235 MultiTextEdit multiEdit= new MultiTextEdit();
236 cuChange.setEdit(multiEdit);
237 return attachChange(cuChange, generateGroups, monitor);
238 }
239
240
241 /**
242 * Attaches the changes of this compilation unit rewrite to the given CU Change. The given
243 * change <b>must</b> either have no root edit, or a MultiTextEdit as a root edit.
244 * The edits in the given change <b>must not</b> overlap with the changes of
245 * this compilation unit.
246 *
247 * @param cuChange existing CompilationUnitChange with a MultiTextEdit root or no root at all.
248 * @param generateGroups <code>true</code> to generate text edit groups, <code>false</code> otherwise
249 * @param monitor the progress monitor or <code>null</code>
250 * @return a change combining the changes of this rewrite and the given rewrite, or <code>null</code> for an empty change
251 * @throws CoreException when text buffer acquisition or import rewrite text edit creation fails
252 */
253 public CompilationUnitChange attachChange(CompilationUnitChange cuChange, boolean generateGroups, IProgressMonitor monitor) throws CoreException {
254 try {
255 boolean needsAstRewrite= fRewrite != null; // TODO: do we need something like ASTRewrite#hasChanges() here?
256 boolean needsImportRemoval= fImportRemover != null && fImportRemover.hasRemovedNodes();
257 boolean needsImportRewrite= fImportRewrite != null && fImportRewrite.hasRecordedChanges() || needsImportRemoval;
258 if (!needsAstRewrite && !needsImportRemoval && !needsImportRewrite)
259 return null;
260
261 MultiTextEdit multiEdit= (MultiTextEdit) cuChange.getEdit();
262 if (multiEdit == null) {
263 multiEdit= new MultiTextEdit();
264 cuChange.setEdit(multiEdit);
265 }
266
267 if (needsAstRewrite) {
268 TextEdit rewriteEdit;
269 if (fRememberContent != null) {
270 rewriteEdit= fRewrite.rewriteAST(fRememberContent, fCu.getJavaProject().getOptions(true));
271 } else {
272 rewriteEdit= fRewrite.rewriteAST();
273 }
274 if (!isEmptyEdit(rewriteEdit)) {
275 multiEdit.addChild(rewriteEdit);
276 if (generateGroups) {
277 for (Iterator<TextEditGroup> iter= fTextEditGroups.iterator(); iter.hasNext();) {
278 TextEditGroup group= iter.next();
279 cuChange.addTextEditGroup(group);
280 }
281 }
282 }
283 }
284 if (needsImportRemoval) {
285 fImportRemover.applyRemoves(getImportRewrite());
286 }
287 if (needsImportRewrite) {
288 TextEdit importsEdit= fImportRewrite.rewriteImports(monitor);
289 if (!isEmptyEdit(importsEdit)) {
290 multiEdit.addChild(importsEdit);
291 String importUpdateName= RefactoringCoreMessages.ASTData_update_imports;
292 cuChange.addTextEditGroup(new TextEditGroup(importUpdateName, importsEdit));
293 }
294 } else {
295
296 }
297 if (isEmptyEdit(multiEdit))
298 return null;
299 return cuChange;
300 } finally {
301 if (monitor != null)
302 monitor.done();
303 }
304 }
305
306 private static boolean isEmptyEdit(TextEdit edit) {
307 return edit.getClass() == MultiTextEdit.class && ! edit.hasChildren();
308 }
309
310 public ICompilationUnit getCu() {
311 return fCu;
312 }
313
314 public CompilationUnit getRoot() {
315 if (fRoot == null)
316 fRoot= new RefactoringASTParser(ASTProvider.SHARED_AST_LEVEL).parse(fCu, fOwner, fResolveBindings, fStatementsRecovery, fBindingsRecovery, null);
317 return fRoot;
318 }
319
320 public AST getAST() {
321 return getRoot().getAST();
322 }
323
324 public ASTRewrite getASTRewrite() {
325 if (fRewrite == null) {
326 fRewrite= ASTRewrite.create(getRoot().getAST());
327 if (fRememberContent != null) { // wain until ast rewrite is accessed first
328 try {
329 fRememberContent.set(fCu.getSource());
330 } catch (JavaModelException e) {
331 fRememberContent= null;
332 }
333 }
334 }
335 return fRewrite;
336 }
337
338 public ImportRewrite getImportRewrite() {
339 if (fImportRewrite == null) {
340 // lazily initialized to avoid lengthy processing in checkInitialConditions(..)
341 try {
342 /* If bindings are to be resolved, then create the AST, so that
343 * ImportRewrite#setUseContextToFilterImplicitImports(boolean) will be set to true
344 * and ContextSensitiveImportRewriteContext etc. can be used. */
345 if (fRoot == null && ! fResolveBindings) {
346 fImportRewrite= StubUtility.createImportRewrite(fCu, true);
347 } else {
348 fImportRewrite= StubUtility.createImportRewrite(getRoot(), true);
349 }
350 } catch (CoreException e) {
351 JavaPlugin.log(e);
352 throw new IllegalStateException(e.getMessage()); // like ASTParser#createAST(..) does
353 }
354 }
355 return fImportRewrite;
356
357 }
358
359 public ImportRemover getImportRemover() {
360 if (fImportRemover == null) {
361 fImportRemover= new ImportRemover(fCu.getJavaProject(), getRoot());
362 }
363 return fImportRemover;
364 }
365
366 public void clearGroupDescriptions() {
367 for (Iterator<TextEditGroup> iter= fTextEditGroups.iterator(); iter.hasNext();) {
368 TextEditGroup group= iter.next();
369 group.clearTextEdits();
370 }
371 }
372}