1 /*******************************************************************************
2  * Copyright (c) 2000, 2016 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  *******************************************************************************/
14 package org.eclipse.jdt.internal.corext.refactoring.structure;
15 
16 import java.util.Collection;
17 import java.util.HashSet;
18 import java.util.Set;
19 
20 import org.eclipse.core.runtime.Assert;
21 import org.eclipse.core.runtime.CoreException;
22 import org.eclipse.core.runtime.IProgressMonitor;
23 import org.eclipse.core.runtime.NullProgressMonitor;
24 import org.eclipse.core.runtime.OperationCanceledException;
25 import org.eclipse.core.runtime.SubProgressMonitor;
26 
27 import org.eclipse.ltk.core.refactoring.Change;
28 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
29 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
30 import org.eclipse.ltk.core.refactoring.TextChange;
31 import org.eclipse.ltk.core.refactoring.TextEditBasedChange;
32 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
33 import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant;
34 import org.eclipse.ltk.core.refactoring.participants.SharableParticipants;
35 
36 import org.eclipse.jdt.core.ICompilationUnit;
37 import org.eclipse.jdt.core.IJavaElement;
38 import org.eclipse.jdt.core.IJavaProject;
39 import org.eclipse.jdt.core.IType;
40 import org.eclipse.jdt.core.JavaModelException;
41 import org.eclipse.jdt.core.dom.ASTNode;
42 import org.eclipse.jdt.core.dom.ASTParser;
43 import org.eclipse.jdt.core.dom.ASTRequestor;
44 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
45 import org.eclipse.jdt.core.dom.CompilationUnit;
46 import org.eclipse.jdt.core.dom.IBinding;
47 import org.eclipse.jdt.core.dom.ITypeBinding;
48 import org.eclipse.jdt.core.dom.NodeFinder;
49 import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
50 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
51 import org.eclipse.jdt.core.refactoring.descriptors.UseSupertypeDescriptor;
52 
53 import org.eclipse.jdt.internal.core.refactoring.descriptors.RefactoringSignatureDescriptorFactory;
54 import org.eclipse.jdt.internal.corext.refactoring.Checks;
55 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
56 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
57 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil;
58 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
59 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
60 import org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeConstraintsModel;
61 import org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeConstraintsSolver;
62 import org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeRefactoringProcessor;
63 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType;
64 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ISourceConstraintVariable;
65 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeConstraintVariable;
66 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
67 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
68 import org.eclipse.jdt.internal.corext.refactoring.util.TextEditBasedChangeManager;
69 import org.eclipse.jdt.internal.corext.util.Messages;
70 
71 import org.eclipse.jdt.ui.JavaElementLabels;
72 
73 import org.eclipse.jdt.internal.ui.JavaPlugin;
74 import org.eclipse.jdt.internal.corext.dom.IASTSharedValues;
75 import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
76 
77 
78 /**
79  * Refactoring processor to replace type occurrences by a super type.
80  */
81 public final class UseSuperTypeProcessor extends SuperTypeRefactoringProcessor {
82 
83 	private static final String IDENTIFIER= "org.eclipse.jdt.ui.useSuperTypeProcessor"; //$NON-NLS-1$
84 
85 	/**
86 	 * Finds the type with the given fully qualified name (generic type
87 	 * parameters included) in the hierarchy.
88 	 *
89 	 * @param type
90 	 *            The hierarchy type to find the super type in
91 	 * @param name
92 	 *            The fully qualified name of the super type
93 	 * @return The found super type, or <code>null</code>
94 	 */
findTypeInHierarchy(final ITypeBinding type, final String name)95 	protected static ITypeBinding findTypeInHierarchy(final ITypeBinding type, final String name) {
96 		if (type.isArray() || type.isPrimitive())
97 			return null;
98 		if (name.equals(type.getTypeDeclaration().getQualifiedName()))
99 			return type;
100 		final ITypeBinding binding= type.getSuperclass();
101 		if (binding != null) {
102 			final ITypeBinding result= findTypeInHierarchy(binding, name);
103 			if (result != null)
104 				return result;
105 		}
106 		for (ITypeBinding b : type.getInterfaces()) {
107 			final ITypeBinding result= findTypeInHierarchy(b, name);
108 			if (result != null)
109 				return result;
110 		}
111 		return null;
112 	}
113 
114 	/** The text change manager */
115 	private TextEditBasedChangeManager fChangeManager= null;
116 
117 	/** The number of files affected by the last change generation */
118 	private int fChanges= 0;
119 
120 	/** The subtype to replace */
121 	private IType fSubType;
122 
123 	/** The supertype as replacement */
124 	private IType fSuperType= null;
125 
126 	/**
127 	 * Creates a new super type processor.
128 	 *
129 	 * @param subType
130 	 *            the subtype to replace its occurrences
131 	 */
UseSuperTypeProcessor(final IType subType)132 	public UseSuperTypeProcessor(final IType subType) {
133 		super(null);
134 		fReplace= true;
135 		fSubType= subType;
136 	}
137 
138 	/**
139 	 * Creates a new super type processor.
140 	 *
141 	 * @param subType
142 	 *            the subtype to replace its occurrences
143 	 * @param superType
144 	 *            the supertype as replacement
145 	 */
UseSuperTypeProcessor(final IType subType, final IType superType)146 	public UseSuperTypeProcessor(final IType subType, final IType superType) {
147 		super(null);
148 		fReplace= true;
149 		fSubType= subType;
150 		fSuperType= superType;
151 	}
152 
153 	/**
154 	 * Creates a new super type processor from refactoring arguments.
155 	 *
156 	 * @param arguments
157 	 *            the refactoring arguments
158 	 * @param status
159 	 *            the resulting status
160 	 */
UseSuperTypeProcessor(JavaRefactoringArguments arguments, RefactoringStatus status)161 	public UseSuperTypeProcessor(JavaRefactoringArguments arguments, RefactoringStatus status) {
162 		super(null);
163 		fReplace= true;
164 		RefactoringStatus initializeStatus= initialize(arguments);
165 		status.merge(initializeStatus);
166 	}
167 
168 	/*
169 	 * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#checkFinalConditions(org.eclipse.core.runtime.IProgressMonitor,org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext)
170 	 */
171 	@Override
checkFinalConditions(final IProgressMonitor monitor, final CheckConditionsContext context)172 	public final RefactoringStatus checkFinalConditions(final IProgressMonitor monitor, final CheckConditionsContext context) throws CoreException, OperationCanceledException {
173 		Assert.isNotNull(monitor);
174 		Assert.isNotNull(context);
175 		final RefactoringStatus status= new RefactoringStatus();
176 		fChangeManager= new TextEditBasedChangeManager();
177 		try {
178 			monitor.beginTask("", 200); //$NON-NLS-1$
179 			monitor.setTaskName(RefactoringCoreMessages.UseSuperTypeProcessor_checking);
180 			fChangeManager= createChangeManager(new SubProgressMonitor(monitor, 200), status);
181 			if (!status.hasFatalError()) {
182 				Checks.addModifiedFilesToChecker(ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits()), context);
183 			}
184 		} finally {
185 			monitor.done();
186 		}
187 		return status;
188 	}
189 
190 	/*
191 	 * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#checkInitialConditions(org.eclipse.core.runtime.IProgressMonitor)
192 	 */
193 	@Override
checkInitialConditions(final IProgressMonitor monitor)194 	public final RefactoringStatus checkInitialConditions(final IProgressMonitor monitor) throws CoreException, OperationCanceledException {
195 		Assert.isNotNull(monitor);
196 		final RefactoringStatus status= new RefactoringStatus();
197 		try {
198 			monitor.beginTask("", 1); //$NON-NLS-1$
199 			monitor.setTaskName(RefactoringCoreMessages.UseSuperTypeProcessor_checking);
200 			// No checks
201 			monitor.worked(1);
202 		} finally {
203 			monitor.done();
204 		}
205 		return status;
206 	}
207 
208 	/*
209 	 * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#createChange(org.eclipse.core.runtime.IProgressMonitor)
210 	 */
211 	@Override
createChange(final IProgressMonitor monitor)212 	public final Change createChange(final IProgressMonitor monitor) throws CoreException, OperationCanceledException {
213 		Assert.isNotNull(monitor);
214 		try {
215 			fChanges= 0;
216 			monitor.beginTask("", 1); //$NON-NLS-1$
217 			monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating);
218 			final TextEditBasedChange[] changes= fChangeManager.getAllChanges();
219 			if (changes != null && changes.length != 0) {
220 				fChanges= changes.length;
221 				IJavaProject project= null;
222 				if (!fSubType.isBinary())
223 					project= fSubType.getJavaProject();
224 				int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE | RefactoringDescriptor.MULTI_CHANGE;
225 				try {
226 					if (fSubType.isLocal() || fSubType.isAnonymous())
227 						flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
228 				} catch (JavaModelException exception) {
229 					JavaPlugin.log(exception);
230 				}
231 				final String name= project != null ? project.getElementName() : null;
232 				final String description= Messages.format(RefactoringCoreMessages.UseSuperTypeProcessor_descriptor_description_short, BasicElementLabels.getJavaElementName(fSuperType.getElementName()));
233 				final String header= Messages.format(RefactoringCoreMessages.UseSuperTypeProcessor_descriptor_description, new String[] { JavaElementLabels.getElementLabel(fSuperType, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getElementLabel(fSubType, JavaElementLabels.ALL_FULLY_QUALIFIED) });
234 				final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(name, this, header);
235 				comment.addSetting(Messages.format(RefactoringCoreMessages.UseSuperTypeProcessor_refactored_element_pattern, JavaElementLabels.getElementLabel(fSuperType, JavaElementLabels.ALL_FULLY_QUALIFIED)));
236 				addSuperTypeSettings(comment, false);
237 				final UseSupertypeDescriptor descriptor= RefactoringSignatureDescriptorFactory.createUseSupertypeDescriptor();
238 				descriptor.setProject(name);
239 				descriptor.setDescription(description);
240 				descriptor.setComment(comment.asString());
241 				descriptor.setFlags(flags);
242 				descriptor.setSubtype(getSubType());
243 				descriptor.setSupertype(getSuperType());
244 				descriptor.setReplaceInstanceof(fInstanceOf);
245 				return new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.UseSupertypeWherePossibleRefactoring_name, fChangeManager.getAllChanges());
246 			}
247 			monitor.worked(1);
248 		} finally {
249 			monitor.done();
250 		}
251 		return null;
252 	}
253 
254 	/**
255 	 * Creates the text change manager for this processor.
256 	 *
257 	 * @param monitor
258 	 *            the progress monitor to display progress
259 	 * @param status
260 	 *            the refactoring status
261 	 * @return the created text change manager
262 	 * @throws JavaModelException
263 	 *             if the method declaration could not be found
264 	 * @throws CoreException
265 	 *             if the changes could not be generated
266 	 */
createChangeManager(final IProgressMonitor monitor, final RefactoringStatus status)267 	protected final TextEditBasedChangeManager createChangeManager(final IProgressMonitor monitor, final RefactoringStatus status) throws JavaModelException, CoreException {
268 		Assert.isNotNull(status);
269 		Assert.isNotNull(monitor);
270 		try {
271 			monitor.beginTask("", 300); //$NON-NLS-1$
272 			monitor.setTaskName(RefactoringCoreMessages.UseSuperTypeProcessor_creating);
273 			final TextEditBasedChangeManager manager= new TextEditBasedChangeManager();
274 			final IJavaProject project= fSubType.getJavaProject();
275 			final ASTParser parser= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL);
276 			parser.setWorkingCopyOwner(fOwner);
277 			parser.setResolveBindings(true);
278 			parser.setProject(project);
279 			parser.setCompilerOptions(RefactoringASTParser.getCompilerOptions(project));
280 			if (fSubType.isBinary() || fSubType.isReadOnly()) {
281 				final IBinding[] bindings= parser.createBindings(new IJavaElement[] { fSubType, fSuperType }, new SubProgressMonitor(monitor, 50));
282 				if (bindings != null && bindings.length == 2 && bindings[0] instanceof ITypeBinding && bindings[1] instanceof ITypeBinding) {
283 					solveSuperTypeConstraints(null, null, fSubType, (ITypeBinding) bindings[0], (ITypeBinding) bindings[1], new SubProgressMonitor(monitor, 100), status);
284 					if (!status.hasFatalError())
285 						rewriteTypeOccurrences(manager, null, null, null, null, new HashSet<String>(), status, new SubProgressMonitor(monitor, 150));
286 				}
287 			} else {
288 				parser.createASTs(new ICompilationUnit[] { fSubType.getCompilationUnit() }, new String[0], new ASTRequestor() {
289 
290 					@Override
291 					public final void acceptAST(final ICompilationUnit unit, final CompilationUnit node) {
292 						try {
293 							final CompilationUnitRewrite subRewrite= new CompilationUnitRewrite(fOwner, unit, node);
294 							final AbstractTypeDeclaration subDeclaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(fSubType, subRewrite.getRoot());
295 							if (subDeclaration != null) {
296 								final ITypeBinding subBinding= subDeclaration.resolveBinding();
297 								if (subBinding != null) {
298 									final ITypeBinding superBinding= findTypeInHierarchy(subBinding, fSuperType.getFullyQualifiedName('.'));
299 									if (superBinding != null) {
300 										solveSuperTypeConstraints(subRewrite.getCu(), subRewrite.getRoot(), fSubType, subBinding, superBinding, new SubProgressMonitor(monitor, 100), status);
301 										if (!status.hasFatalError()) {
302 											rewriteTypeOccurrences(manager, this, subRewrite, subRewrite.getCu(), subRewrite.getRoot(), new HashSet<String>(), status, new SubProgressMonitor(monitor, 200));
303 											final TextChange change= subRewrite.createChange(true);
304 											if (change != null)
305 												manager.manage(subRewrite.getCu(), change);
306 										}
307 									}
308 								}
309 							}
310 						} catch (CoreException exception) {
311 							JavaPlugin.log(exception);
312 							status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.UseSuperTypeProcessor_internal_error));
313 						}
314 					}
315 
316 					@Override
317 					public final void acceptBinding(final String key, final IBinding binding) {
318 						// Do nothing
319 					}
320 				}, new NullProgressMonitor());
321 			}
322 			return manager;
323 		} finally {
324 			monitor.done();
325 		}
326 	}
327 
328 	/*
329 	 * @see org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeRefactoringProcessor#createContraintSolver(org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeConstraintsModel)
330 	 */
331 	@Override
createContraintSolver(final SuperTypeConstraintsModel model)332 	protected final SuperTypeConstraintsSolver createContraintSolver(final SuperTypeConstraintsModel model) {
333 		return new SuperTypeConstraintsSolver(model);
334 	}
335 
336 	/**
337 	 * Returns the number of files that are affected from the last change
338 	 * generation.
339 	 *
340 	 * @return The number of files which are affected
341 	 */
getChanges()342 	public final int getChanges() {
343 		return fChanges;
344 	}
345 
346 	/*
347 	 * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#getElements()
348 	 */
349 	@Override
getElements()350 	public final Object[] getElements() {
351 		return new Object[] { fSubType };
352 	}
353 
354 	/*
355 	 * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#getIdentifier()
356 	 */
357 	@Override
getIdentifier()358 	public final String getIdentifier() {
359 		return IDENTIFIER;
360 	}
361 
362 	/*
363 	 * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#getProcessorName()
364 	 */
365 	@Override
getProcessorName()366 	public final String getProcessorName() {
367 		return RefactoringCoreMessages.UseSuperTypeProcessor_name;
368 	}
369 
370 	/**
371 	 * Returns the subtype to be replaced.
372 	 *
373 	 * @return The subtype to be replaced
374 	 */
getSubType()375 	public final IType getSubType() {
376 		return fSubType;
377 	}
378 
379 	/**
380 	 * Returns the supertype as replacement.
381 	 *
382 	 * @return The supertype as replacement
383 	 */
getSuperType()384 	public final IType getSuperType() {
385 		return fSuperType;
386 	}
387 
initialize(JavaRefactoringArguments extended)388 	private final RefactoringStatus initialize(JavaRefactoringArguments extended) {
389 		String handle= extended.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT);
390 		if (handle != null) {
391 			final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(extended.getProject(), handle, false);
392 			if (element == null || !element.exists() || element.getElementType() != IJavaElement.TYPE)
393 				return JavaRefactoringDescriptorUtil.createInputFatalStatus(element, getProcessorName(), IJavaRefactorings.USE_SUPER_TYPE);
394 			else
395 				fSubType= (IType) element;
396 		} else
397 			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT));
398 		handle= extended.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + 1);
399 		if (handle != null) {
400 			final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(extended.getProject(), handle, false);
401 			if (element == null || !element.exists() || element.getElementType() != IJavaElement.TYPE)
402 				return JavaRefactoringDescriptorUtil.createInputFatalStatus(element, getProcessorName(), IJavaRefactorings.USE_SUPER_TYPE);
403 			else
404 				fSuperType= (IType) element;
405 		} else
406 			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + 1));
407 		final String instance= extended.getAttribute(ATTRIBUTE_INSTANCEOF);
408 		if (instance != null) {
409 			fInstanceOf= Boolean.parseBoolean(instance);
410 		} else
411 			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_INSTANCEOF));
412 		return new RefactoringStatus();
413 	}
414 
415 	/*
416 	 * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#isApplicable()
417 	 */
418 	@Override
isApplicable()419 	public final boolean isApplicable() throws CoreException {
420 		return Checks.isAvailable(fSubType) && Checks.isAvailable(fSuperType) && !fSubType.isAnonymous() && !fSubType.isAnnotation() && !fSuperType.isAnonymous() && !fSuperType.isAnnotation() && !fSuperType.isEnum();
421 	}
422 
423 	/*
424 	 * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#loadParticipants(org.eclipse.ltk.core.refactoring.RefactoringStatus,org.eclipse.ltk.core.refactoring.participants.SharableParticipants)
425 	 */
426 	@Override
loadParticipants(final RefactoringStatus status, final SharableParticipants sharedParticipants)427 	public final RefactoringParticipant[] loadParticipants(final RefactoringStatus status, final SharableParticipants sharedParticipants) throws CoreException {
428 		return new RefactoringParticipant[0];
429 	}
430 
431 	@Override
rewriteTypeOccurrences(final TextEditBasedChangeManager manager, final ASTRequestor requestor, final CompilationUnitRewrite rewrite, final ICompilationUnit unit, final CompilationUnit node, final Set<String> replacements, final IProgressMonitor monitor)432 	protected final void rewriteTypeOccurrences(final TextEditBasedChangeManager manager, final ASTRequestor requestor, final CompilationUnitRewrite rewrite, final ICompilationUnit unit, final CompilationUnit node, final Set<String> replacements, final IProgressMonitor monitor) throws CoreException {
433 		try {
434 			monitor.beginTask("", 100); //$NON-NLS-1$
435 			monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating);
436 			final Collection<ITypeConstraintVariable> collection= fTypeOccurrences.get(unit);
437 			if (collection != null && !collection.isEmpty()) {
438 				final IProgressMonitor subMonitor= new SubProgressMonitor(monitor, 100);
439 				try {
440 					subMonitor.beginTask("", collection.size() * 10); //$NON-NLS-1$
441 					subMonitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating);
442 					TType estimate= null;
443 					ISourceConstraintVariable variable= null;
444 					CompilationUnitRewrite currentRewrite= null;
445 					final ICompilationUnit sourceUnit= rewrite.getCu();
446 					if (sourceUnit.equals(unit))
447 						currentRewrite= rewrite;
448 					else
449 						currentRewrite= new CompilationUnitRewrite(fOwner, unit, node);
450 					for (ITypeConstraintVariable iTypeConstraintVariable : collection) {
451 						variable= iTypeConstraintVariable;
452 						estimate= (TType) variable.getData(SuperTypeConstraintsSolver.DATA_TYPE_ESTIMATE);
453 						if (estimate != null && variable instanceof ITypeConstraintVariable) {
454 							final ASTNode result= NodeFinder.perform(node, ((ITypeConstraintVariable) variable).getRange().getSourceRange());
455 							if (result != null)
456 								rewriteTypeOccurrence(estimate, currentRewrite, result, currentRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.SuperTypeRefactoringProcessor_update_type_occurrence, SET_SUPER_TYPE));
457 						}
458 						subMonitor.worked(10);
459 					}
460 					if (!sourceUnit.equals(unit)) {
461 						final TextChange change= currentRewrite.createChange(true);
462 						if (change != null)
463 							manager.manage(unit, change);
464 					}
465 				} finally {
466 					subMonitor.done();
467 				}
468 			}
469 		} finally {
470 			monitor.done();
471 		}
472 	}
473 
474 	/**
475 	 * Sets the supertype as replacement.
476 	 *
477 	 * @param type
478 	 *            The supertype to set
479 	 */
setSuperType(final IType type)480 	public final void setSuperType(final IType type) {
481 		Assert.isNotNull(type);
482 
483 		fSuperType= type;
484 	}
485 }
486