1 /*******************************************************************************
2  * Copyright (c) 2006, 2020 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  *     Benjamin Muskalla - 228950: [pull up] exception if target calls super with multiple parameters
14  *     Jerome Cambon <jerome.cambon@oracle.com> - [code style] don't generate redundant modifiers "public static final abstract" for interface members - https://bugs.eclipse.org/71627
15  *******************************************************************************/
16 package org.eclipse.jdt.internal.corext.refactoring.structure;
17 
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.Collection;
21 import java.util.Collections;
22 import java.util.HashMap;
23 import java.util.HashSet;
24 import java.util.Iterator;
25 import java.util.LinkedHashSet;
26 import java.util.LinkedList;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Map.Entry;
30 import java.util.Set;
31 
32 import org.eclipse.core.runtime.Assert;
33 import org.eclipse.core.runtime.CoreException;
34 import org.eclipse.core.runtime.IProgressMonitor;
35 import org.eclipse.core.runtime.NullProgressMonitor;
36 import org.eclipse.core.runtime.OperationCanceledException;
37 import org.eclipse.core.runtime.SubProgressMonitor;
38 
39 import org.eclipse.text.edits.MalformedTreeException;
40 import org.eclipse.text.edits.TextEdit;
41 
42 import org.eclipse.jface.text.BadLocationException;
43 import org.eclipse.jface.text.Document;
44 import org.eclipse.jface.text.IDocument;
45 
46 import org.eclipse.ltk.core.refactoring.Change;
47 import org.eclipse.ltk.core.refactoring.GroupCategory;
48 import org.eclipse.ltk.core.refactoring.GroupCategorySet;
49 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
50 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
51 import org.eclipse.ltk.core.refactoring.RefactoringStatusContext;
52 import org.eclipse.ltk.core.refactoring.TextChange;
53 import org.eclipse.ltk.core.refactoring.TextEditBasedChange;
54 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
55 
56 import org.eclipse.jdt.core.Flags;
57 import org.eclipse.jdt.core.ICompilationUnit;
58 import org.eclipse.jdt.core.IField;
59 import org.eclipse.jdt.core.IJavaElement;
60 import org.eclipse.jdt.core.IJavaProject;
61 import org.eclipse.jdt.core.IMember;
62 import org.eclipse.jdt.core.IMethod;
63 import org.eclipse.jdt.core.IType;
64 import org.eclipse.jdt.core.ITypeHierarchy;
65 import org.eclipse.jdt.core.ITypeParameter;
66 import org.eclipse.jdt.core.JavaModelException;
67 import org.eclipse.jdt.core.Signature;
68 import org.eclipse.jdt.core.dom.AST;
69 import org.eclipse.jdt.core.dom.ASTNode;
70 import org.eclipse.jdt.core.dom.ASTParser;
71 import org.eclipse.jdt.core.dom.ASTRequestor;
72 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
73 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
74 import org.eclipse.jdt.core.dom.Block;
75 import org.eclipse.jdt.core.dom.BodyDeclaration;
76 import org.eclipse.jdt.core.dom.CompilationUnit;
77 import org.eclipse.jdt.core.dom.Expression;
78 import org.eclipse.jdt.core.dom.FieldAccess;
79 import org.eclipse.jdt.core.dom.FieldDeclaration;
80 import org.eclipse.jdt.core.dom.IBinding;
81 import org.eclipse.jdt.core.dom.IMethodBinding;
82 import org.eclipse.jdt.core.dom.ITypeBinding;
83 import org.eclipse.jdt.core.dom.Javadoc;
84 import org.eclipse.jdt.core.dom.MethodDeclaration;
85 import org.eclipse.jdt.core.dom.MethodInvocation;
86 import org.eclipse.jdt.core.dom.Modifier;
87 import org.eclipse.jdt.core.dom.Name;
88 import org.eclipse.jdt.core.dom.NodeFinder;
89 import org.eclipse.jdt.core.dom.QualifiedName;
90 import org.eclipse.jdt.core.dom.ReturnStatement;
91 import org.eclipse.jdt.core.dom.SimpleName;
92 import org.eclipse.jdt.core.dom.SimpleType;
93 import org.eclipse.jdt.core.dom.SuperFieldAccess;
94 import org.eclipse.jdt.core.dom.SuperMethodInvocation;
95 import org.eclipse.jdt.core.dom.ThisExpression;
96 import org.eclipse.jdt.core.dom.TypeDeclarationStatement;
97 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
98 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
99 import org.eclipse.jdt.core.dom.rewrite.ITrackedNodePosition;
100 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
101 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
102 import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
103 import org.eclipse.jdt.core.manipulation.CodeGeneration;
104 import org.eclipse.jdt.core.refactoring.CompilationUnitChange;
105 import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
106 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
107 import org.eclipse.jdt.core.refactoring.descriptors.PullUpDescriptor;
108 
109 import org.eclipse.jdt.internal.core.manipulation.StubUtility;
110 import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
111 import org.eclipse.jdt.internal.core.manipulation.util.Strings;
112 import org.eclipse.jdt.internal.core.refactoring.descriptors.RefactoringSignatureDescriptorFactory;
113 import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings;
114 import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
115 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility2Core;
116 import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
117 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
118 import org.eclipse.jdt.internal.corext.dom.Bindings;
119 import org.eclipse.jdt.internal.corext.dom.BodyDeclarationRewrite;
120 import org.eclipse.jdt.internal.corext.dom.IASTSharedValues;
121 import org.eclipse.jdt.internal.corext.dom.ModifierRewrite;
122 import org.eclipse.jdt.internal.corext.refactoring.Checks;
123 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
124 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
125 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil;
126 import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
127 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
128 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
129 import org.eclipse.jdt.internal.corext.refactoring.rename.MethodChecks;
130 import org.eclipse.jdt.internal.corext.refactoring.reorg.SourceReferenceUtil;
131 import org.eclipse.jdt.internal.corext.refactoring.structure.MemberVisibilityAdjustor.IncomingMemberVisibilityAdjustment;
132 import org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeConstraintsSolver;
133 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.CompilationUnitRange;
134 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType;
135 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ISourceConstraintVariable;
136 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeConstraintVariable;
137 import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil;
138 import org.eclipse.jdt.internal.corext.refactoring.util.JavaStatusContext;
139 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
140 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
141 import org.eclipse.jdt.internal.corext.refactoring.util.TextEditBasedChangeManager;
142 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
143 import org.eclipse.jdt.internal.corext.util.JdtFlags;
144 import org.eclipse.jdt.internal.corext.util.Messages;
145 
146 import org.eclipse.jdt.ui.JavaElementLabels;
147 
148 import org.eclipse.jdt.internal.ui.JavaPlugin;
149 import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings;
150 import org.eclipse.jdt.internal.ui.preferences.formatter.FormatterProfileManager;
151 
152 /**
153  * Refactoring processor for the pull up refactoring.
154  *
155  * @since 3.2
156  */
157 public class PullUpRefactoringProcessor extends HierarchyProcessor {
158 
159 	/**
160 	 * AST node visitor which performs the actual mapping.
161 	 */
162 	private static class PullUpAstNodeMapper extends TypeVariableMapper {
163 
164 		/** Are we in an anonymous class declaration? */
165 		private boolean fAnonymousClassDeclaration= false;
166 
167 		/** The source compilation unit rewrite to use */
168 		private final CompilationUnitRewrite fSourceRewriter;
169 
170 		/** The super reference type */
171 		private final IType fSuperReferenceType;
172 
173 		/** The target compilation unit rewrite to use */
174 		private final CompilationUnitRewrite fTargetRewriter;
175 
176 		/** Are we in a type declaration statement? */
177 		private boolean fTypeDeclarationStatement= false;
178 
179 		/** The binding of the enclosing method */
180 		private final IMethodBinding fEnclosingMethod;
181 
182 		/**
183 		 * Creates a new pull up ast node mapper.
184 		 *
185 		 * @param sourceRewriter
186 		 *            the source compilation unit rewrite to use
187 		 * @param targetRewriter
188 		 *            the target compilation unit rewrite to use
189 		 * @param rewrite
190 		 *            the AST rewrite to use
191 		 * @param type
192 		 *            the super reference type
193 		 * @param mapping
194 		 *            the type variable mapping
195 		 * @param enclosing the binding of the enclosing method
196 		 */
PullUpAstNodeMapper(final CompilationUnitRewrite sourceRewriter, final CompilationUnitRewrite targetRewriter, final ASTRewrite rewrite, final IType type, final TypeVariableMaplet[] mapping, final IMethodBinding enclosing)197 		public PullUpAstNodeMapper(final CompilationUnitRewrite sourceRewriter, final CompilationUnitRewrite targetRewriter, final ASTRewrite rewrite, final IType type, final TypeVariableMaplet[] mapping, final IMethodBinding enclosing) {
198 			super(rewrite, mapping);
199 			Assert.isNotNull(rewrite);
200 			Assert.isNotNull(type);
201 			fSourceRewriter= sourceRewriter;
202 			fTargetRewriter= targetRewriter;
203 			fSuperReferenceType= type;
204 			fEnclosingMethod= enclosing;
205 		}
206 
207 		@Override
endVisit(final AnonymousClassDeclaration node)208 		public final void endVisit(final AnonymousClassDeclaration node) {
209 			fAnonymousClassDeclaration= false;
210 			super.endVisit(node);
211 		}
212 
213 		@Override
endVisit(final TypeDeclarationStatement node)214 		public final void endVisit(final TypeDeclarationStatement node) {
215 			fTypeDeclarationStatement= false;
216 			super.endVisit(node);
217 		}
218 
219 		@Override
visit(final AnonymousClassDeclaration node)220 		public final boolean visit(final AnonymousClassDeclaration node) {
221 			fAnonymousClassDeclaration= true;
222 			return super.visit(node);
223 		}
224 
225 		@Override
visit(final SuperFieldAccess node)226 		public final boolean visit(final SuperFieldAccess node) {
227 			if (!fAnonymousClassDeclaration && !fTypeDeclarationStatement) {
228 				final AST ast= node.getAST();
229 				final FieldAccess access= ast.newFieldAccess();
230 				access.setExpression(ast.newThisExpression());
231 				access.setName(ast.newSimpleName(node.getName().getIdentifier()));
232 				fRewrite.replace(node, access, null);
233 				if (!fSourceRewriter.getCu().equals(fTargetRewriter.getCu()))
234 					fSourceRewriter.getImportRemover().registerRemovedNode(node);
235 				return true;
236 			}
237 			return false;
238 		}
239 
240 		@Override
visit(final SuperMethodInvocation node)241 		public final boolean visit(final SuperMethodInvocation node) {
242 			if (!fAnonymousClassDeclaration && !fTypeDeclarationStatement) {
243 				final IBinding superBinding= node.getName().resolveBinding();
244 				if (superBinding instanceof IMethodBinding) {
245 					final IMethodBinding extended= (IMethodBinding) superBinding;
246 					if (fEnclosingMethod != null && fEnclosingMethod.overrides(extended))
247 						return true;
248 					final ITypeBinding declaringBinding= extended.getDeclaringClass();
249 					if (declaringBinding != null) {
250 						final IType type= (IType) declaringBinding.getJavaElement();
251 						if (!fSuperReferenceType.equals(type))
252 							return true;
253 					}
254 				}
255 				final AST ast= node.getAST();
256 				final ThisExpression expression= ast.newThisExpression();
257 				final MethodInvocation invocation= ast.newMethodInvocation();
258 				final SimpleName simple= ast.newSimpleName(node.getName().getIdentifier());
259 				invocation.setName(simple);
260 				invocation.setExpression(expression);
261 				final List<Expression> arguments= node.arguments();
262 				if (arguments != null && arguments.size() > 0) {
263 					final ListRewrite rewriter= fRewrite.getListRewrite(invocation, MethodInvocation.ARGUMENTS_PROPERTY);
264 					ListRewrite superRewriter= fRewrite.getListRewrite(node, SuperMethodInvocation.ARGUMENTS_PROPERTY);
265 					ASTNode copyTarget= superRewriter.createCopyTarget(arguments.get(0), arguments.get(arguments.size() - 1));
266 					rewriter.insertLast(copyTarget, null);
267 				}
268 				fRewrite.replace(node, invocation, null);
269 				if (!fSourceRewriter.getCu().equals(fTargetRewriter.getCu()))
270 					fSourceRewriter.getImportRemover().registerRemovedNode(node);
271 				return true;
272 			}
273 			return false;
274 		}
275 
276 		@Override
visit(final TypeDeclarationStatement node)277 		public final boolean visit(final TypeDeclarationStatement node) {
278 			fTypeDeclarationStatement= true;
279 			return super.visit(node);
280 		}
281 	}
282 
283 	protected static final String ATTRIBUTE_ABSTRACT= "abstract"; //$NON-NLS-1$
284 
285 	protected static final String ATTRIBUTE_DELETE= "delete"; //$NON-NLS-1$
286 
287 	protected static final String ATTRIBUTE_PULL= "pull"; //$NON-NLS-1$
288 
289 	protected static final String ATTRIBUTE_STUBS= "stubs"; //$NON-NLS-1$
290 
291 	private static final String IDENTIFIER= "org.eclipse.jdt.ui.pullUpProcessor"; //$NON-NLS-1$
292 
293 	/** The pull up group category set */
294 	private static final GroupCategorySet SET_PULL_UP= new GroupCategorySet(new GroupCategory("org.eclipse.jdt.internal.corext.pullUp", //$NON-NLS-1$
295 			RefactoringCoreMessages.PullUpRefactoring_category_name, RefactoringCoreMessages.PullUpRefactoring_category_description));
296 
addMatchingMember(final Map<IMember, Set<IMember>> mapping, final IMember key, final IMember matchingMember)297 	private static void addMatchingMember(final Map<IMember, Set<IMember>> mapping, final IMember key, final IMember matchingMember) {
298 		Set<IMember> matchingSet;
299 		if (mapping.containsKey(key)) {
300 			matchingSet= mapping.get(key);
301 		} else {
302 			matchingSet= new HashSet<>();
303 			mapping.put(key, matchingSet);
304 		}
305 		Assert.isTrue(!matchingSet.contains(matchingMember));
306 		matchingSet.add(matchingMember);
307 	}
308 
createMethodStub(final MethodDeclaration method, final AST ast, ICompilationUnit cu, ASTRewrite rewrite, String targetTypeName)309 	private static Block createMethodStub(final MethodDeclaration method, final AST ast, ICompilationUnit cu, ASTRewrite rewrite, String targetTypeName) {
310 		final Block body= ast.newBlock();
311 		final Expression expression= ASTNodeFactory.newDefaultExpression(ast, method.getReturnType2(), method.getExtraDimensions());
312 		try {
313 			String delimiter= cu.findRecommendedLineSeparator();
314 			String bodyStatement= ""; //$NON-NLS-1$
315 			if (expression != null) {
316 				final ReturnStatement returnStatement= ast.newReturnStatement();
317 				returnStatement.setExpression(expression);
318 				bodyStatement= ASTNodes.asFormattedString(returnStatement, 0, delimiter, FormatterProfileManager.getProjectSettings(cu.getJavaProject()));
319 			}
320 			String placeHolder= CodeGeneration.getMethodBodyContent(cu, targetTypeName, method.getName().getIdentifier(), false, bodyStatement, delimiter);
321 			if (placeHolder != null) {
322 				ReturnStatement todoNode= (ReturnStatement) rewrite.createStringPlaceholder(placeHolder, ASTNode.RETURN_STATEMENT);
323 				body.statements().add(todoNode);
324 			}
325 		} catch (CoreException e) {
326 			// return empty body
327 		}
328 		return body;
329 	}
330 
getAffectedSubTypes(final ITypeHierarchy hierarchy, final IType type)331 	private static Set<IType> getAffectedSubTypes(final ITypeHierarchy hierarchy, final IType type) throws JavaModelException {
332 		 IType[] types= null;
333 		 final boolean isInterface= type.isInterface();
334 		if (isInterface) {
335 			 final Collection<IType> remove= new ArrayList<>();
336 			 final List<IType> list= new ArrayList<>(Arrays.asList(hierarchy.getSubtypes(type)));
337 			 for (IType element : list) {
338 				if (element.isInterface())
339 					remove.add(element);
340 			}
341 			 list.removeAll(remove);
342 			 types= list.toArray(new IType[list.size()]);
343 		 } else
344 			 types= hierarchy.getSubclasses(type);
345 		final Set<IType> result= new HashSet<>();
346 		for (IType type2 : types) {
347 			if (!isInterface && JdtFlags.isAbstract(type2))
348 				result.addAll(getAffectedSubTypes(hierarchy, type2));
349 			else
350 				result.add(type2);
351 		}
352 		return result;
353 	}
354 
getMembers(final IMember[] members, final int type)355 	private static IMember[] getMembers(final IMember[] members, final int type) {
356 		final List<IJavaElement> list= Arrays.asList(JavaElementUtil.getElementsOfType(members, type));
357 		return list.toArray(new IMember[list.size()]);
358 	}
359 
mergeMaps(final Map<IMember, Set<IMember>> result, final Map<IMember, Set<IMember>> map)360 	private static void mergeMaps(final Map<IMember, Set<IMember>> result, final Map<IMember, Set<IMember>> map) {
361 		for (final Entry<IMember, Set<IMember>> entry : result.entrySet()) {
362 			final IMember key= entry.getKey();
363 			if (map.containsKey(key)) {
364 				final Set<IMember> resultSet= entry.getValue();
365 				final Set<IMember> mapSet= map.get(key);
366 				resultSet.addAll(mapSet);
367 			}
368 		}
369 	}
370 
upgradeMap(final Map<IMember, Set<IMember>> result, final Map<IMember, Set<IMember>> map)371 	private static void upgradeMap(final Map<IMember, Set<IMember>> result, final Map<IMember, Set<IMember>> map) {
372 		for (final Entry<IMember, Set<IMember>> entry : map.entrySet()) {
373 			final IMember key= entry.getKey();
374 			if (!result.containsKey(key)) {
375 				final Set<IMember> mapSet= entry.getValue();
376 				final Set<IMember> resultSet= new HashSet<>(mapSet);
377 				result.put(key, resultSet);
378 			}
379 		}
380 	}
381 
382 	/** The methods to be declared abstract */
383 	protected IMethod[] fAbstractMethods= new IMethod[0];
384 
385 	/** The cached supertype hierarchy of the declaring type */
386 	private ITypeHierarchy fCachedDeclaringSuperTypeHierarchy;
387 
388 	/** The cached type hierarchy of the destination type */
389 	private ITypeHierarchy fCachedDestinationTypeHierarchy;
390 
391 	/** The cached set of skipped supertypes */
392 	private Set<IType> fCachedSkippedSuperTypes;
393 
394 	/** The map of compilation units to compilation unit rewrites */
395 	protected Map<ICompilationUnit, CompilationUnitRewrite> fCompilationUnitRewrites;
396 
397 	/** Should method stubs be generated in subtypes? */
398 	protected boolean fCreateMethodStubs= true;
399 
400 	/** The methods to be deleted in subtypes */
401 	protected IMethod[] fDeletedMethods= new IMethod[0];
402 
403 	/** The destination type */
404 	protected IType fDestinationType;
405 
406 	/**
407 	 * Creates a new pull up refactoring processor.
408 	 *
409 	 * @param members
410 	 *            the members to pull up
411 	 * @param settings
412 	 *            the code generation settings
413 	 */
PullUpRefactoringProcessor(final IMember[] members, final CodeGenerationSettings settings)414 	public PullUpRefactoringProcessor(final IMember[] members, final CodeGenerationSettings settings) {
415 		this(members, settings, false);
416 	}
417 
418 	/**
419 	 * Creates a new pull up processor from refactoring arguments.
420 	 *
421 	 * @param arguments
422 	 *            the refactoring arguments
423 	 * @param status
424 	 *            the resulting status
425 	 */
PullUpRefactoringProcessor(JavaRefactoringArguments arguments, RefactoringStatus status)426 	public PullUpRefactoringProcessor(JavaRefactoringArguments arguments, RefactoringStatus status) {
427 		this(null, null, false);
428 		RefactoringStatus initializeStatus= initialize(arguments);
429 		status.merge(initializeStatus);
430 	}
431 
432 	/**
433 	 * Creates a new pull up refactoring processor.
434 	 *
435 	 * @param members
436 	 *            the members to pull up, or <code>null</code> if invoked by
437 	 *            scripting
438 	 * @param settings
439 	 *            the code generation settings, or <code>null</code> if
440 	 *            invoked by scripting
441 	 * @param layer
442 	 *            <code>true</code> to create a working copy layer,
443 	 *            <code>false</code> otherwise
444 	 */
PullUpRefactoringProcessor(final IMember[] members, final CodeGenerationSettings settings, final boolean layer)445 	protected PullUpRefactoringProcessor(final IMember[] members, final CodeGenerationSettings settings, final boolean layer) {
446 		super(members, settings, layer);
447 		if (members != null) {
448 			final IType type= RefactoringAvailabilityTester.getTopLevelType(fMembersToMove);
449 			try {
450 				if (type != null && RefactoringAvailabilityTester.getPullUpMembers(type).length != 0) {
451 					fCachedDeclaringType= RefactoringAvailabilityTester.getTopLevelType(fMembersToMove);
452 					fMembersToMove= new IMember[0];
453 				}
454 			} catch (JavaModelException exception) {
455 				JavaPlugin.log(exception);
456 			}
457 		}
458 	}
459 
addAllRequiredPullableMembers(final List<IMember> queue, final IMember member, final IProgressMonitor monitor)460 	private void addAllRequiredPullableMembers(final List<IMember> queue, final IMember member, final IProgressMonitor monitor) throws JavaModelException {
461 		Assert.isNotNull(queue);
462 		Assert.isNotNull(member);
463 		Assert.isNotNull(monitor);
464 		SubProgressMonitor sub= null;
465 		try {
466 			monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_calculating_required, 6);
467 
468 			final IMethod[] requiredMethods= ReferenceFinderUtil.getMethodsReferencedIn(new IJavaElement[] { member}, fOwner, new SubProgressMonitor(monitor, 1));
469 			sub= new SubProgressMonitor(monitor, 1);
470 			boolean isStatic= false;
471 			try {
472 				sub.beginTask(RefactoringCoreMessages.PullUpRefactoring_calculating_required, requiredMethods.length);
473 				isStatic= JdtFlags.isStatic(member);
474 				for (IMethod requiredMethod : requiredMethods) {
475 					if (isStatic && !JdtFlags.isStatic(requiredMethod))
476 						continue;
477 					if (isRequiredPullableMember(queue, requiredMethod)
478 							&& (!MethodChecks.isVirtual(requiredMethod) || !isAvailableInDestination(requiredMethod, new SubProgressMonitor(sub, 1))))
479 						queue.add(requiredMethod);
480 				}
481 			} finally {
482 				sub.done();
483 			}
484 			final IField[] requiredFields= ReferenceFinderUtil.getFieldsReferencedIn(new IJavaElement[] { member}, fOwner, new SubProgressMonitor(monitor, 1));
485 			sub= new SubProgressMonitor(monitor, 1);
486 			try {
487 				sub.beginTask(RefactoringCoreMessages.PullUpRefactoring_calculating_required, requiredFields.length);
488 				isStatic= JdtFlags.isStatic(member);
489 				for (final IField requiredField : requiredFields) {
490 					if (isStatic && !JdtFlags.isStatic(requiredField))
491 						continue;
492 					if (isRequiredPullableMember(queue, requiredField))
493 						queue.add(requiredField);
494 				}
495 			} finally {
496 				sub.done();
497 			}
498 			final IType[] requiredTypes= ReferenceFinderUtil.getTypesReferencedIn(new IJavaElement[] { member}, fOwner, new SubProgressMonitor(monitor, 1));
499 			sub= new SubProgressMonitor(monitor, 1);
500 			try {
501 				sub.beginTask(RefactoringCoreMessages.PullUpRefactoring_calculating_required, requiredMethods.length);
502 				isStatic= JdtFlags.isStatic(member);
503 				for (final IType requiredType : requiredTypes) {
504 					if (isStatic && !JdtFlags.isStatic(requiredType))
505 						continue;
506 					if (isRequiredPullableMember(queue, requiredType))
507 						queue.add(requiredType);
508 				}
509 			} finally {
510 				sub.done();
511 			}
512 		} finally {
513 			monitor.done();
514 		}
515 	}
516 
addMethodStubForAbstractMethod(final IMethod sourceMethod, final CompilationUnit declaringCuNode, final AbstractTypeDeclaration typeToCreateStubIn, final ICompilationUnit newCu, final CompilationUnitRewrite rewriter, final Map<IMember, IncomingMemberVisibilityAdjustment> adjustments, final IProgressMonitor monitor, final RefactoringStatus status)517 	private void addMethodStubForAbstractMethod(final IMethod sourceMethod, final CompilationUnit declaringCuNode, final AbstractTypeDeclaration typeToCreateStubIn, final ICompilationUnit newCu, final CompilationUnitRewrite rewriter, final Map<IMember, IncomingMemberVisibilityAdjustment> adjustments, final IProgressMonitor monitor, final RefactoringStatus status) throws CoreException {
518 		final MethodDeclaration methodToCreateStubFor= ASTNodeSearchUtil.getMethodDeclarationNode(sourceMethod, declaringCuNode);
519 		final AST ast= rewriter.getRoot().getAST();
520 		final MethodDeclaration newMethod= ast.newMethodDeclaration();
521 		ASTRewrite astRewrite= rewriter.getASTRewrite();
522 		newMethod.setBody(createMethodStub(methodToCreateStubFor, ast, newCu, astRewrite, Bindings.getFullyQualifiedName(typeToCreateStubIn.resolveBinding())));
523 		newMethod.setConstructor(false);
524 		copyExtraDimensions(methodToCreateStubFor, newMethod);
525 		int modifiers= getModifiersWithUpdatedVisibility(sourceMethod, JdtFlags.clearFlag(Modifier.NATIVE | Modifier.ABSTRACT, methodToCreateStubFor.getModifiers()), adjustments,
526 				new SubProgressMonitor(monitor, 1), false, status);
527 		if (getDestinationType().isInterface()) {
528 			modifiers= modifiers | Modifier.PUBLIC;
529 		}
530 		newMethod.modifiers().addAll(ASTNodeFactory.newModifiers(ast, modifiers));
531 		newMethod.setName(((SimpleName) ASTNode.copySubtree(ast, methodToCreateStubFor.getName())));
532 		final TypeVariableMaplet[] mapping= TypeVariableUtil.composeMappings(TypeVariableUtil.subTypeToSuperType(getDeclaringType(), getDestinationType()), TypeVariableUtil.superTypeToInheritedType(getDestinationType(), ((IType) typeToCreateStubIn.resolveBinding().getJavaElement())));
533 		copyReturnType(astRewrite, getDeclaringType().getCompilationUnit(), methodToCreateStubFor, newMethod, mapping);
534 		copyParameters(astRewrite, getDeclaringType().getCompilationUnit(), methodToCreateStubFor, newMethod, mapping);
535 		copyThrownExceptions(methodToCreateStubFor, newMethod);
536 		copyTypeParameters(methodToCreateStubFor, newMethod);
537 		newMethod.setJavadoc(createJavadocForStub(typeToCreateStubIn.getName().getIdentifier(), methodToCreateStubFor, newMethod, newCu, astRewrite));
538 		ImportRewrite importRewrite= rewriter.getImportRewrite();
539 		ImportRewriteContext context= new ContextSensitiveImportRewriteContext(typeToCreateStubIn, importRewrite);
540 		ImportRewriteUtil.addImports(rewriter, context, methodToCreateStubFor, new HashMap<Name, String>(), new HashMap<Name, String>(), true);
541 		IJavaProject javaProject= newCu.getJavaProject();
542 		CodeGenerationSettings codeGenerationSettings= JavaPreferencesSettings.getCodeGenerationSettings(javaProject);
543 		StubUtility2Core.addOverrideAnnotation(codeGenerationSettings, javaProject, astRewrite, importRewrite, newMethod, getDeclaringType().isInterface(),
544 				rewriter.createCategorizedGroupDescription(RefactoringCoreMessages.PullUpRefactoring_add_override_annotation, SET_PULL_UP));
545 		astRewrite.getListRewrite(typeToCreateStubIn, typeToCreateStubIn.getBodyDeclarationsProperty()).insertAt(newMethod, BodyDeclarationRewrite.getInsertionIndex(newMethod, typeToCreateStubIn.bodyDeclarations()), rewriter.createCategorizedGroupDescription(RefactoringCoreMessages.PullUpRefactoring_add_method_stub, SET_PULL_UP));
546 	}
547 
addNecessaryMethodStubs(final List<IType> affected, final CompilationUnit root, final CompilationUnitRewrite unitRewriter, final Map<IMember, IncomingMemberVisibilityAdjustment> adjustments, final IProgressMonitor monitor, final RefactoringStatus status)548 	private void addNecessaryMethodStubs(final List<IType> affected, final CompilationUnit root, final CompilationUnitRewrite unitRewriter, final Map<IMember, IncomingMemberVisibilityAdjustment> adjustments, final IProgressMonitor monitor, final RefactoringStatus status) throws CoreException {
549 		final IType declaringType= getDeclaringType();
550 		final IMethod[] methods= getAbstractMethods();
551 		try {
552 			monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, affected.size());
553 			for (IType type : affected) {
554 				if (type.equals(declaringType))
555 					continue;
556 				final AbstractTypeDeclaration declaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(type, unitRewriter.getRoot());
557 				final ICompilationUnit unit= type.getCompilationUnit();
558 				final IProgressMonitor subMonitor= new SubProgressMonitor(monitor, 1);
559 				try {
560 					subMonitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, methods.length);
561 					for (final IMethod method : methods) {
562 						if (null == JavaModelUtil.findMethod(method.getElementName(), method.getParameterTypes(), method.isConstructor(), type)) {
563 							addMethodStubForAbstractMethod(method, root, declaration, unit, unitRewriter, adjustments, new SubProgressMonitor(subMonitor, 1), status);
564 						}
565 					}
566 					subMonitor.done();
567 				} finally {
568 					subMonitor.done();
569 				}
570 			}
571 		} finally {
572 			monitor.done();
573 		}
574 	}
575 
576 	@Override
canBeAccessedFrom(final IMember member, final IType target, final ITypeHierarchy hierarchy)577 	protected boolean canBeAccessedFrom(final IMember member, final IType target, final ITypeHierarchy hierarchy) throws JavaModelException {
578 		if (super.canBeAccessedFrom(member, target, hierarchy)) {
579 			if (target.isInterface())
580 				return true;
581 			if (target.equals(member.getDeclaringType()))
582 				return true;
583 			if (target.equals(member))
584 				return true;
585 			if (member instanceof IMethod) {
586 				final IMethod method= (IMethod) member;
587 				final IMethod stub= target.getMethod(method.getElementName(), method.getParameterTypes());
588 				if (stub.exists())
589 					return true;
590 			}
591 			if (member.getDeclaringType() == null) {
592 				if (!(member instanceof IType))
593 					return false;
594 				if (JdtFlags.isPublic(member))
595 					return true;
596 				if (!JdtFlags.isPackageVisible(member))
597 					return false;
598 				if (JavaModelUtil.isSamePackage(((IType) member).getPackageFragment(), target.getPackageFragment()))
599 					return true;
600 				final IType type= member.getDeclaringType();
601 				if (type != null)
602 					return hierarchy.contains(type);
603 				return false;
604 			}
605 			final IType declaringType= member.getDeclaringType();
606 			if (!canBeAccessedFrom(declaringType, target, hierarchy))
607 				return false;
608 			if (declaringType.equals(getDeclaringType()))
609 				return false;
610 			return true;
611 		}
612 		return false;
613 	}
614 
checkAccessedFields(final IProgressMonitor monitor, final ITypeHierarchy hierarchy)615 	private RefactoringStatus checkAccessedFields(final IProgressMonitor monitor, final ITypeHierarchy hierarchy) throws JavaModelException {
616 		monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking_referenced_elements, 2);
617 		final RefactoringStatus result= new RefactoringStatus();
618 
619 		final List<IMember> pulledUpList= Arrays.asList(fMembersToMove);
620 		final List<IMember> deletedList= Arrays.asList(getMembersToDelete(new SubProgressMonitor(monitor, 1)));
621 		final IField[] accessedFields= ReferenceFinderUtil.getFieldsReferencedIn(fMembersToMove, fOwner, new SubProgressMonitor(monitor, 1));
622 
623 		final IType destination= getDestinationType();
624 		for (final IField field : accessedFields) {
625 			if (!field.exists())
626 				continue;
627 
628 			boolean isAccessible= pulledUpList.contains(field) || deletedList.contains(field) || canBeAccessedFrom(field, destination, hierarchy) || Flags.isEnum(field.getFlags());
629 			if (!isAccessible) {
630 				final String message= Messages.format(RefactoringCoreMessages.PullUpRefactoring_field_not_accessible, new String[] { JavaElementLabels.getTextLabel(field, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(destination, JavaElementLabels.ALL_FULLY_QUALIFIED)});
631 				result.addError(message, JavaStatusContext.create(field));
632 			} else if (getSkippedSuperTypes(new SubProgressMonitor(monitor, 1)).contains(field.getDeclaringType())) {
633 				final String message= Messages.format(RefactoringCoreMessages.PullUpRefactoring_field_cannot_be_accessed, new String[] { JavaElementLabels.getTextLabel(field, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(destination, JavaElementLabels.ALL_FULLY_QUALIFIED)});
634 				result.addError(message, JavaStatusContext.create(field));
635 			}
636 		}
637 		monitor.done();
638 		return result;
639 	}
640 
checkAccessedMethods(final IProgressMonitor monitor, final ITypeHierarchy hierarchy)641 	private RefactoringStatus checkAccessedMethods(final IProgressMonitor monitor, final ITypeHierarchy hierarchy) throws JavaModelException {
642 		monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking_referenced_elements, 2);
643 		final RefactoringStatus result= new RefactoringStatus();
644 
645 		final List<IMember> pulledUpList= Arrays.asList(fMembersToMove);
646 		final List<IMethod> declaredAbstractList= Arrays.asList(fAbstractMethods);
647 		final List<IMember> deletedList= Arrays.asList(getMembersToDelete(new SubProgressMonitor(monitor, 1)));
648 		final IMethod[] accessedMethods= ReferenceFinderUtil.getMethodsReferencedIn(fMembersToMove, fOwner, new SubProgressMonitor(monitor, 1));
649 
650 		final IType destination= getDestinationType();
651 		for (final IMethod method : accessedMethods) {
652 			if (!method.exists())
653 				continue;
654 			boolean isAccessible= pulledUpList.contains(method) || deletedList.contains(method) || declaredAbstractList.contains(method) || canBeAccessedFrom(method, destination, hierarchy);
655 			if (!isAccessible) {
656 				final String message= Messages.format(RefactoringCoreMessages.PullUpRefactoring_method_not_accessible, new String[] { JavaElementLabels.getTextLabel(method, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(destination, JavaElementLabels.ALL_FULLY_QUALIFIED)});
657 				result.addError(message, JavaStatusContext.create(method));
658 			} else if (getSkippedSuperTypes(new SubProgressMonitor(monitor, 1)).contains(method.getDeclaringType())) {
659 				final String[] keys= { JavaElementLabels.getTextLabel(method, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(destination, JavaElementLabels.ALL_FULLY_QUALIFIED)};
660 				final String message= Messages.format(RefactoringCoreMessages.PullUpRefactoring_method_cannot_be_accessed, keys);
661 				result.addError(message, JavaStatusContext.create(method));
662 			}
663 		}
664 		monitor.done();
665 		return result;
666 	}
667 
checkAccessedTypes(final IProgressMonitor monitor, final ITypeHierarchy hierarchy)668 	private RefactoringStatus checkAccessedTypes(final IProgressMonitor monitor, final ITypeHierarchy hierarchy) throws JavaModelException {
669 		final RefactoringStatus result= new RefactoringStatus();
670 		final IType destination= getDestinationType();
671 		final List<IMember> pulledUpList= Arrays.asList(fMembersToMove);
672 		for (final IType type : getTypesReferencedInMovedMembers(monitor)) {
673 			if (!type.exists())
674 				continue;
675 
676 			if (!canBeAccessedFrom(type, destination, hierarchy) && !pulledUpList.contains(type)) {
677 				final String message= Messages.format(RefactoringCoreMessages.PullUpRefactoring_type_not_accessible, new String[] { JavaElementLabels.getTextLabel(type, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(destination, JavaElementLabels.ALL_FULLY_QUALIFIED)});
678 				result.addError(message, JavaStatusContext.create(type));
679 			}
680 		}
681 		monitor.done();
682 		return result;
683 	}
684 
checkAccesses(final IProgressMonitor monitor)685 	private RefactoringStatus checkAccesses(final IProgressMonitor monitor) throws JavaModelException {
686 		final RefactoringStatus result= new RefactoringStatus();
687 		try {
688 			monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking_referenced_elements, 4);
689 			final ITypeHierarchy hierarchy= getDestinationType().newSupertypeHierarchy(fOwner, new SubProgressMonitor(monitor, 1));
690 			result.merge(checkAccessedTypes(new SubProgressMonitor(monitor, 1), hierarchy));
691 			result.merge(checkAccessedFields(new SubProgressMonitor(monitor, 1), hierarchy));
692 			result.merge(checkAccessedMethods(new SubProgressMonitor(monitor, 1), hierarchy));
693 		} finally {
694 			monitor.done();
695 		}
696 		return result;
697 	}
698 
checkAccessModifiers(final RefactoringStatus result, final Set<IMember> notDeletedMembersInSubtypes)699 	private void checkAccessModifiers(final RefactoringStatus result, final Set<IMember> notDeletedMembersInSubtypes) throws JavaModelException {
700 		if (fDestinationType.isInterface())
701 			return;
702 		final List<IMethod> toDeclareAbstract= Arrays.asList(fAbstractMethods);
703 		for (IMember member : notDeletedMembersInSubtypes) {
704 			if (member.getElementType() == IJavaElement.METHOD && !toDeclareAbstract.contains(member)) {
705 				final IMethod method= ((IMethod) member);
706 				if (method.getDeclaringType().getPackageFragment().equals(fDestinationType.getPackageFragment())) {
707 					if (JdtFlags.isPrivate(method))
708 						result.addError(Messages.format(RefactoringCoreMessages.PullUpRefactoring_lower_default_visibility, new String[] { JavaElementLabels.getTextLabel(method, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(method.getDeclaringType(), JavaElementLabels.ALL_FULLY_QUALIFIED)}), JavaStatusContext.create(method));
709 				} else if (!JdtFlags.isPublic(method) && !JdtFlags.isProtected(method))
710 					result.addError(Messages.format(RefactoringCoreMessages.PullUpRefactoring_lower_protected_visibility, new String[] { JavaElementLabels.getTextLabel(method, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(method.getDeclaringType(), JavaElementLabels.ALL_FULLY_QUALIFIED)}), JavaStatusContext.create(method));
711 			}
712 		}
713 	}
714 
checkDeclaringSuperTypes(final IProgressMonitor monitor)715 	protected RefactoringStatus checkDeclaringSuperTypes(final IProgressMonitor monitor) throws JavaModelException {
716 		final RefactoringStatus result= new RefactoringStatus();
717 		if (getCandidateTypes(result, monitor).length == 0 && !result.hasFatalError()) {
718 			final String msg= Messages.format(RefactoringCoreMessages.PullUpRefactoring_not_this_type, new String[] { JavaElementLabels.getTextLabel(getDeclaringType(), JavaElementLabels.ALL_FULLY_QUALIFIED)});
719 			return RefactoringStatus.createFatalErrorStatus(msg);
720 		}
721 		return result;
722 	}
723 
724 	@Override
checkDeclaringType(final IProgressMonitor monitor)725 	protected RefactoringStatus checkDeclaringType(final IProgressMonitor monitor) throws JavaModelException {
726 		final RefactoringStatus status= super.checkDeclaringType(monitor);
727 		if (getDeclaringType().getFullyQualifiedName('.').equals("java.lang.Object")) //$NON-NLS-1$
728 			status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.PullUpRefactoring_no_java_lang_Object));
729 		status.merge(checkDeclaringSuperTypes(monitor));
730 		return status;
731 	}
732 
checkFieldTypes(final IProgressMonitor monitor, final RefactoringStatus status)733 	private void checkFieldTypes(final IProgressMonitor monitor, final RefactoringStatus status) throws JavaModelException {
734 		final Map<IMember, Set<IMember>> mapping= getMatchingMembers(getDestinationTypeHierarchy(monitor), getDestinationType(), true);
735 		for (IMember element : fMembersToMove) {
736 			if (element.getElementType() != IJavaElement.FIELD)
737 				continue;
738 			final IField field= (IField) element;
739 			final String type= Signature.toString(field.getTypeSignature());
740 			Assert.isTrue(mapping.containsKey(field));
741 			for (IMember member : mapping.get(field)) {
742 				final IField matchingField= (IField) member;
743 				if (field.equals(matchingField))
744 					continue;
745 				if (type.equals(Signature.toString(matchingField.getTypeSignature())))
746 					continue;
747 				final String[] keys= { JavaElementLabels.getTextLabel(matchingField, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(matchingField.getDeclaringType(), JavaElementLabels.ALL_FULLY_QUALIFIED)};
748 				final String message= Messages.format(RefactoringCoreMessages.PullUpRefactoring_different_field_type, keys);
749 				final RefactoringStatusContext context= JavaStatusContext.create(matchingField.getCompilationUnit(), matchingField.getSourceRange());
750 				status.addError(message, context);
751 			}
752 		}
753 	}
754 
755 	@Override
checkFinalConditions(final IProgressMonitor monitor, final CheckConditionsContext context)756 	public RefactoringStatus checkFinalConditions(final IProgressMonitor monitor, final CheckConditionsContext context) throws CoreException, OperationCanceledException {
757 		try {
758 			monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, 12);
759 			clearCaches();
760 
761 			final RefactoringStatus result= new RefactoringStatus();
762 			result.merge(createWorkingCopyLayer(new SubProgressMonitor(monitor, 4)));
763 			if (result.hasFatalError())
764 				return result;
765 			if (monitor.isCanceled())
766 				throw new OperationCanceledException();
767 			result.merge(checkGenericDeclaringType(new SubProgressMonitor(monitor, 1)));
768 			result.merge(checkFinalFields(new SubProgressMonitor(monitor, 1)));
769 			if (monitor.isCanceled())
770 				throw new OperationCanceledException();
771 			result.merge(checkAccesses(new SubProgressMonitor(monitor, 1)));
772 			result.merge(checkMembersInTypeAndAllSubtypes(new SubProgressMonitor(monitor, 2)));
773 			result.merge(checkIfSkippingOverElements(new SubProgressMonitor(monitor, 1)));
774 			if (monitor.isCanceled())
775 				throw new OperationCanceledException();
776 			if (!JdtFlags.isAbstract(getDestinationType()) && getAbstractMethods().length > 0)
777 				result.merge(checkConstructorCalls(getDestinationType(), new SubProgressMonitor(monitor, 1)));
778 			else
779 				monitor.worked(1);
780 			if (result.hasFatalError())
781 				return result;
782 			fCompilationUnitRewrites= new HashMap<>(3);
783 			result.merge(checkProjectCompliance(getCompilationUnitRewrite(fCompilationUnitRewrites, getDeclaringType().getCompilationUnit()), getDestinationType(), fMembersToMove));
784 			fChangeManager= createChangeManager(new SubProgressMonitor(monitor, 1), result);
785 
786 			Checks.addModifiedFilesToChecker(ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits()), context);
787 
788 			return result;
789 		} finally {
790 			monitor.done();
791 		}
792 	}
793 
checkFinalFields(final IProgressMonitor monitor)794 	private RefactoringStatus checkFinalFields(final IProgressMonitor monitor) throws JavaModelException {
795 		final RefactoringStatus result= new RefactoringStatus();
796 		monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, fMembersToMove.length);
797 		for (final IMember member : fMembersToMove) {
798 			if (member.getElementType() == IJavaElement.FIELD) {
799 				if (!JdtFlags.isStatic(member)) {
800 					if (JdtFlags.isFinal(member)) {
801 						final RefactoringStatusContext context= JavaStatusContext.create(member);
802 						result.addWarning(RefactoringCoreMessages.PullUpRefactoring_final_fields, context);
803 					} else if (getDestinationType().isInterface()) {
804 						final RefactoringStatusContext context= JavaStatusContext.create(member);
805 						result.addWarning(RefactoringCoreMessages.PullUpRefactoring_non_final_pull_up_to_interface, context);
806 					}
807 				}
808 			}
809 			monitor.worked(1);
810 			if (monitor.isCanceled())
811 				throw new OperationCanceledException();
812 		}
813 		monitor.done();
814 		return result;
815 	}
816 
checkGenericDeclaringType(final SubProgressMonitor monitor)817 	private RefactoringStatus checkGenericDeclaringType(final SubProgressMonitor monitor) throws JavaModelException {
818 		Assert.isNotNull(monitor);
819 
820 		final RefactoringStatus status= new RefactoringStatus();
821 		try {
822 			final IMember[] pullables= getMembersToMove();
823 			monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, pullables.length);
824 
825 			final IType declaring= getDeclaringType();
826 			final ITypeParameter[] parameters= declaring.getTypeParameters();
827 			if (parameters.length > 0) {
828 				final TypeVariableMaplet[] mapping= TypeVariableUtil.subTypeToInheritedType(declaring);
829 				IMember member= null;
830 				int length= 0;
831 				for (IMember pullable : pullables) {
832 					member= pullable;
833 					final String[] unmapped= TypeVariableUtil.getUnmappedVariables(mapping, declaring, member);
834 					length= unmapped.length;
835 
836 					String superClassLabel= BasicElementLabels.getJavaElementName(declaring.getSuperclassName());
837 					switch (length) {
838 						case 0:
839 							break;
840 						case 1:
841 							status.addError(Messages.format(RefactoringCoreMessages.PullUpRefactoring_Type_variable_not_available, new String[] { unmapped[0], superClassLabel}), JavaStatusContext.create(member));
842 							break;
843 						case 2:
844 							status.addError(Messages.format(RefactoringCoreMessages.PullUpRefactoring_Type_variable2_not_available, new String[] { unmapped[0], unmapped[1], superClassLabel}), JavaStatusContext.create(member));
845 							break;
846 						case 3:
847 							status.addError(Messages.format(RefactoringCoreMessages.PullUpRefactoring_Type_variable3_not_available, new String[] { unmapped[0], unmapped[1], unmapped[2], superClassLabel}), JavaStatusContext.create(member));
848 							break;
849 						default:
850 							status.addError(Messages.format(RefactoringCoreMessages.PullUpRefactoring_Type_variables_not_available, new String[] { superClassLabel}), JavaStatusContext.create(member));
851 					}
852 					monitor.worked(1);
853 					if (monitor.isCanceled())
854 						throw new OperationCanceledException();
855 				}
856 			}
857 		} finally {
858 			monitor.done();
859 		}
860 		return status;
861 	}
862 
checkIfDeclaredIn(final IMember element, final IType type)863 	private RefactoringStatus checkIfDeclaredIn(final IMember element, final IType type) throws JavaModelException {
864 		if (element instanceof IMethod)
865 			return checkIfMethodDeclaredIn((IMethod) element, type);
866 		else if (element instanceof IField)
867 			return checkIfFieldDeclaredIn((IField) element, type);
868 		else if (element instanceof IType)
869 			return checkIfTypeDeclaredIn((IType) element, type);
870 		Assert.isTrue(false);
871 		return null;
872 	}
873 
checkIfFieldDeclaredIn(final IField iField, final IType type)874 	private RefactoringStatus checkIfFieldDeclaredIn(final IField iField, final IType type) throws JavaModelException {
875 		final IField fieldInType= type.getField(iField.getElementName());
876 		if (!fieldInType.exists() || !iField.getTypeSignature().equals(fieldInType.getTypeSignature())) {
877 			return null;
878 		}
879 		final String[] keys= { JavaElementLabels.getTextLabel(fieldInType, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(type, JavaElementLabels.ALL_FULLY_QUALIFIED)};
880 		final String msg= Messages.format(RefactoringCoreMessages.PullUpRefactoring_Field_declared_in_class, keys);
881 		final RefactoringStatusContext context= JavaStatusContext.create(fieldInType);
882 		return RefactoringStatus.createWarningStatus(msg, context);
883 	}
884 
checkIfMethodDeclaredIn(final IMethod iMethod, final IType type)885 	private RefactoringStatus checkIfMethodDeclaredIn(final IMethod iMethod, final IType type) throws JavaModelException {
886 		final IMethod methodInType= JavaModelUtil.findMethod(iMethod.getElementName(), iMethod.getParameterTypes(), iMethod.isConstructor(), type);
887 		if (methodInType == null || !methodInType.exists())
888 			return null;
889 		final String[] keys= { JavaElementLabels.getTextLabel(methodInType, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(type, JavaElementLabels.ALL_FULLY_QUALIFIED)};
890 		final String msg= Messages.format(RefactoringCoreMessages.PullUpRefactoring_Method_declared_in_class, keys);
891 		final RefactoringStatusContext context= JavaStatusContext.create(methodInType);
892 		return RefactoringStatus.createWarningStatus(msg, context);
893 	}
894 
checkIfSkippingOverElements(final IProgressMonitor monitor)895 	private RefactoringStatus checkIfSkippingOverElements(final IProgressMonitor monitor) throws JavaModelException {
896 		monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, 1);
897 		try {
898 			final Set<IType> skippedTypes= getSkippedSuperTypes(new SubProgressMonitor(monitor, 1));
899 			final IType[] skipped= skippedTypes.toArray(new IType[skippedTypes.size()]);
900 			final RefactoringStatus result= new RefactoringStatus();
901 			for (final IMember element : fMembersToMove) {
902 				for (IType element2 : skipped) {
903 					result.merge(checkIfDeclaredIn(element, element2));
904 				}
905 			}
906 			return result;
907 		} finally {
908 			monitor.done();
909 		}
910 	}
911 
checkIfTypeDeclaredIn(final IType iType, final IType type)912 	private RefactoringStatus checkIfTypeDeclaredIn(final IType iType, final IType type) {
913 		final IType typeInType= type.getType(iType.getElementName());
914 		if (!typeInType.exists())
915 			return null;
916 		final String[] keys= { JavaElementLabels.getTextLabel(typeInType, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(type, JavaElementLabels.ALL_FULLY_QUALIFIED)};
917 		final String msg= Messages.format(RefactoringCoreMessages.PullUpRefactoring_Type_declared_in_class, keys);
918 		final RefactoringStatusContext context= JavaStatusContext.create(typeInType);
919 		return RefactoringStatus.createWarningStatus(msg, context);
920 	}
921 
922 	@Override
checkInitialConditions(final IProgressMonitor monitor)923 	public RefactoringStatus checkInitialConditions(final IProgressMonitor monitor) throws CoreException, OperationCanceledException {
924 		try {
925 			monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, 1);
926 			final RefactoringStatus status= new RefactoringStatus();
927 			status.merge(checkDeclaringType(new SubProgressMonitor(monitor, 1)));
928 			if (status.hasFatalError())
929 				return status;
930 			status.merge(checkIfMembersExist());
931 			if (status.hasFatalError())
932 				return status;
933 			return status;
934 		} finally {
935 			monitor.done();
936 		}
937 	}
938 
checkMembersInDestinationType(final RefactoringStatus status, final Set<IMember> set)939 	private void checkMembersInDestinationType(final RefactoringStatus status, final Set<IMember> set) throws JavaModelException {
940 		final IMember[] destinationMembers= getCreatedDestinationMembers();
941 		final List<IMember> list= new ArrayList<>(destinationMembers.length);
942 		list.addAll(Arrays.asList(destinationMembers));
943 		list.addAll(set);
944 		list.removeAll(Arrays.asList(fDeletedMethods));
945 		final IMember[] members= list.toArray(new IMember[list.size()]);
946 		status.merge(MemberCheckUtil.checkMembersInDestinationType(members, getDestinationType()));
947 	}
948 
checkMembersInTypeAndAllSubtypes(final IProgressMonitor monitor)949 	private RefactoringStatus checkMembersInTypeAndAllSubtypes(final IProgressMonitor monitor) throws JavaModelException {
950 		final RefactoringStatus result= new RefactoringStatus();
951 		monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, 3);
952 		final Set<IMember> notDeletedMembers= getNotDeletedMembers(new SubProgressMonitor(monitor, 1));
953 		final Set<IMember> notDeletedMembersInTargetType= new HashSet<>();
954 		final Set<IMember> notDeletedMembersInSubtypes= new HashSet<>();
955 		for (IMember member : notDeletedMembers) {
956 			if (getDestinationType().equals(member.getDeclaringType()))
957 				notDeletedMembersInTargetType.add(member);
958 			else
959 				notDeletedMembersInSubtypes.add(member);
960 		}
961 		checkMembersInDestinationType(result, notDeletedMembersInTargetType);
962 		checkAccessModifiers(result, notDeletedMembersInSubtypes);
963 		checkMethodReturnTypes(new SubProgressMonitor(monitor, 1), result, notDeletedMembersInSubtypes);
964 		checkFieldTypes(new SubProgressMonitor(monitor, 1), result);
965 		monitor.done();
966 		return result;
967 	}
968 
checkMethodReturnTypes(final IProgressMonitor monitor, final RefactoringStatus status, final Set<IMember> notDeletedMembersInSubtypes)969 	private void checkMethodReturnTypes(final IProgressMonitor monitor, final RefactoringStatus status, final Set<IMember> notDeletedMembersInSubtypes) throws JavaModelException {
970 		final Map<IMember, Set<IMember>> mapping= getMatchingMembers(getDestinationTypeHierarchy(monitor), getDestinationType(), true);
971 		for (IMember member : getCreatedDestinationMembers()) {
972 			if (member.getElementType() != IJavaElement.METHOD)
973 				continue;
974 			final IMethod method= (IMethod) member;
975 			if (mapping.containsKey(method)) {
976 				final Set<IMember> set= mapping.get(method);
977 				if (set != null) {
978 					final String returnType= Signature.toString(Signature.getReturnType(method.getSignature()).toString());
979 					for (IMember iMember : set) {
980 						final IMethod matchingMethod= (IMethod) iMember;
981 						if (method.equals(matchingMethod))
982 							continue;
983 						if (!notDeletedMembersInSubtypes.contains(matchingMethod))
984 							continue;
985 						if (returnType.equals(Signature.toString(Signature.getReturnType(matchingMethod.getSignature()).toString())))
986 							continue;
987 						final String[] keys= { JavaElementLabels.getTextLabel(matchingMethod, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(matchingMethod.getDeclaringType(), JavaElementLabels.ALL_FULLY_QUALIFIED)};
988 						final String message= Messages.format(RefactoringCoreMessages.PullUpRefactoring_different_method_return_type, keys);
989 						final RefactoringStatusContext context= JavaStatusContext.create(matchingMethod.getCompilationUnit(), matchingMethod.getNameRange());
990 						status.addError(message, context);
991 					}
992 				}
993 			}
994 		}
995 	}
996 
997 	@Override
clearCaches()998 	protected void clearCaches() {
999 		super.clearCaches();
1000 		fCachedMembersReferences.clear();
1001 		fCachedDestinationTypeHierarchy= null;
1002 		fCachedDeclaringSuperTypeHierarchy= null;
1003 	}
1004 
copyBodyOfPulledUpMethod(final CompilationUnitRewrite sourceRewrite, final CompilationUnitRewrite targetRewrite, final IMethod method, final MethodDeclaration oldMethod, final MethodDeclaration newMethod, final TypeVariableMaplet[] mapping, final IProgressMonitor monitor)1005 	private void copyBodyOfPulledUpMethod(final CompilationUnitRewrite sourceRewrite, final CompilationUnitRewrite targetRewrite, final IMethod method, final MethodDeclaration oldMethod, final MethodDeclaration newMethod, final TypeVariableMaplet[] mapping, final IProgressMonitor monitor) throws JavaModelException {
1006 		final Block body= oldMethod.getBody();
1007 		if (body == null) {
1008 			newMethod.setBody(null);
1009 			return;
1010 		}
1011 		try {
1012 			final IDocument document= new Document(method.getCompilationUnit().getBuffer().getContents());
1013 			final ASTRewrite rewrite= ASTRewrite.create(body.getAST());
1014 			final ITrackedNodePosition position= rewrite.track(body);
1015 			body.accept(new PullUpAstNodeMapper(sourceRewrite, targetRewrite, rewrite, getDeclaringSuperTypeHierarchy(monitor).getSuperclass(getDeclaringType()), mapping, oldMethod.resolveBinding()));
1016 			rewrite.rewriteAST(document, method.getJavaProject().getOptions(true)).apply(document, TextEdit.NONE);
1017 			String content= document.get(position.getStartPosition(), position.getLength());
1018 			final String[] lines= Strings.convertIntoLines(content);
1019 			Strings.trimIndentation(lines, method.getJavaProject(), false);
1020 			content= Strings.concatenate(lines, StubUtility.getLineDelimiterUsed(method));
1021 			newMethod.setBody((Block) targetRewrite.getASTRewrite().createStringPlaceholder(content, ASTNode.BLOCK));
1022 		} catch (MalformedTreeException exception) {
1023 			JavaPlugin.log(exception);
1024 		} catch (BadLocationException exception) {
1025 			JavaPlugin.log(exception);
1026 		}
1027 	}
1028 
createAbstractMethod(final IMethod sourceMethod, final CompilationUnitRewrite sourceRewriter, final CompilationUnit declaringCuNode, final AbstractTypeDeclaration destination, final TypeVariableMaplet[] mapping, final CompilationUnitRewrite targetRewrite, final Map<IMember, IncomingMemberVisibilityAdjustment> adjustments, final IProgressMonitor monitor, final RefactoringStatus status)1029 	private void createAbstractMethod(final IMethod sourceMethod, final CompilationUnitRewrite sourceRewriter, final CompilationUnit declaringCuNode, final AbstractTypeDeclaration destination, final TypeVariableMaplet[] mapping, final CompilationUnitRewrite targetRewrite, final Map<IMember, IncomingMemberVisibilityAdjustment> adjustments, final IProgressMonitor monitor, final RefactoringStatus status) throws JavaModelException {
1030 		final MethodDeclaration oldMethod= ASTNodeSearchUtil.getMethodDeclarationNode(sourceMethod, declaringCuNode);
1031 		ITypeBinding destinationBinding= destination.resolveBinding();
1032 		StubUtility2Core.addOverrideAnnotation(fSettings, sourceMethod.getJavaProject(), sourceRewriter.getASTRewrite(), sourceRewriter.getImportRewrite(), oldMethod,
1033 				destinationBinding == null ? false : destinationBinding.isInterface(),
1034 				sourceRewriter.createCategorizedGroupDescription(RefactoringCoreMessages.PullUpRefactoring_add_override_annotation, SET_PULL_UP));
1035 		final MethodDeclaration newMethod= targetRewrite.getAST().newMethodDeclaration();
1036 		newMethod.setBody(null);
1037 		newMethod.setConstructor(false);
1038 		copyExtraDimensions(oldMethod, newMethod);
1039 
1040 		final Javadoc oldJavadoc= oldMethod.getJavadoc();
1041 		if (oldJavadoc != null) {
1042 			String newJavadocString= ASTNodes.getNodeSource(oldJavadoc, false, true);
1043 			if (newJavadocString != null) {
1044 				newMethod.setJavadoc((Javadoc) targetRewrite.getASTRewrite().createStringPlaceholder(newJavadocString, ASTNode.JAVADOC));
1045 			}
1046 		}
1047 
1048 		int modifiers= getModifiersWithUpdatedVisibility(sourceMethod, Modifier.ABSTRACT | JdtFlags.clearFlag(Modifier.NATIVE | Modifier.FINAL, sourceMethod.getFlags()), adjustments, monitor, false, status);
1049 		if (oldMethod.isVarargs())
1050 			modifiers&= ~Flags.AccVarargs;
1051 		newMethod.modifiers().addAll(ASTNodeFactory.newModifiers(targetRewrite.getAST(), modifiers));
1052 		newMethod.setName(((SimpleName) ASTNode.copySubtree(targetRewrite.getAST(), oldMethod.getName())));
1053 		copyReturnType(targetRewrite.getASTRewrite(), getDeclaringType().getCompilationUnit(), oldMethod, newMethod, mapping);
1054 		copyParameters(targetRewrite.getASTRewrite(), getDeclaringType().getCompilationUnit(), oldMethod, newMethod, mapping);
1055 		copyThrownExceptions(oldMethod, newMethod);
1056 		copyTypeParameters(oldMethod, newMethod);
1057 		ImportRewriteContext context= new ContextSensitiveImportRewriteContext(destination, targetRewrite.getImportRewrite());
1058 		ImportRewriteUtil.addImports(targetRewrite, context, oldMethod, new HashMap<Name, String>(), new HashMap<Name, String>(), true);
1059 		targetRewrite.getASTRewrite().getListRewrite(destination, destination.getBodyDeclarationsProperty()).insertAt(newMethod, org.eclipse.jdt.internal.corext.dom.BodyDeclarationRewrite.getInsertionIndex(newMethod, destination.bodyDeclarations()), targetRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.PullUpRefactoring_add_abstract_method, SET_PULL_UP));
1060 	}
1061 
1062 	@Override
createChange(final IProgressMonitor monitor)1063 	public Change createChange(final IProgressMonitor monitor) throws CoreException, OperationCanceledException {
1064 		try {
1065 			final Map<String, String> arguments= new HashMap<>();
1066 			String project= null;
1067 			final IType declaring= getDeclaringType();
1068 			final IJavaProject javaProject= declaring.getJavaProject();
1069 			if (javaProject != null)
1070 				project= javaProject.getElementName();
1071 			int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE | RefactoringDescriptor.MULTI_CHANGE;
1072 			try {
1073 				if (declaring.isLocal() || declaring.isAnonymous())
1074 					flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
1075 			} catch (JavaModelException exception) {
1076 				JavaPlugin.log(exception);
1077 			}
1078 			final String description= fMembersToMove.length == 1 ? Messages.format(RefactoringCoreMessages.PullUpRefactoring_descriptor_description_short, new String[] { JavaElementLabels.getElementLabel(fMembersToMove[0], JavaElementLabels.ALL_DEFAULT), JavaElementLabels.getElementLabel(fDestinationType, JavaElementLabels.ALL_DEFAULT)}) : Messages.format(RefactoringCoreMessages.PullUpRefactoring_descriptor_description_short_multiple, BasicElementLabels.getJavaElementName(fDestinationType.getElementName()));
1079 			final String header= fMembersToMove.length == 1 ? Messages.format(RefactoringCoreMessages.PullUpRefactoring_descriptor_description_full, new String[] { JavaElementLabels.getElementLabel(fMembersToMove[0], JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getElementLabel(declaring, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getElementLabel(fDestinationType, JavaElementLabels.ALL_FULLY_QUALIFIED)}) : Messages.format(RefactoringCoreMessages.PullUpRefactoring_descriptor_description, new String[] { JavaElementLabels.getElementLabel(declaring, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getElementLabel(fDestinationType, JavaElementLabels.ALL_FULLY_QUALIFIED)});
1080 			final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header);
1081 			comment.addSetting(Messages.format(RefactoringCoreMessages.MoveStaticMembersProcessor_target_element_pattern, JavaElementLabels.getElementLabel(fDestinationType, JavaElementLabels.ALL_FULLY_QUALIFIED)));
1082 			addSuperTypeSettings(comment, true);
1083 			final PullUpDescriptor descriptor= RefactoringSignatureDescriptorFactory.createPullUpDescriptor(project, description, comment.asString(), arguments, flags);
1084 			arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT, JavaRefactoringDescriptorUtil.elementToHandle(project, fDestinationType));
1085 			arguments.put(ATTRIBUTE_REPLACE, Boolean.toString(fReplace));
1086 			arguments.put(ATTRIBUTE_INSTANCEOF, Boolean.toString(fInstanceOf));
1087 			arguments.put(ATTRIBUTE_STUBS, Boolean.toString(fCreateMethodStubs));
1088 			arguments.put(ATTRIBUTE_PULL, Integer.toString(fMembersToMove.length));
1089 			for (int offset= 0; offset < fMembersToMove.length; offset++)
1090 				arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + (offset + 1), JavaRefactoringDescriptorUtil.elementToHandle(project, fMembersToMove[offset]));
1091 			arguments.put(ATTRIBUTE_DELETE, Integer.toString(fDeletedMethods.length));
1092 			for (int offset= 0; offset < fDeletedMethods.length; offset++)
1093 				arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + (offset + fMembersToMove.length + 1), JavaRefactoringDescriptorUtil.elementToHandle(project, fDeletedMethods[offset]));
1094 			arguments.put(ATTRIBUTE_ABSTRACT, Integer.toString(fAbstractMethods.length));
1095 			for (int offset= 0; offset < fAbstractMethods.length; offset++)
1096 				arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + (offset + fMembersToMove.length + fDeletedMethods.length + 1), JavaRefactoringDescriptorUtil.elementToHandle(project, fAbstractMethods[offset]));
1097 			return new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.PullUpRefactoring_Pull_Up, fChangeManager.getAllChanges());
1098 		} finally {
1099 			monitor.done();
1100 			clearCaches();
1101 		}
1102 	}
1103 
createChangeManager(final IProgressMonitor monitor, final RefactoringStatus status)1104 	private TextEditBasedChangeManager createChangeManager(final IProgressMonitor monitor, final RefactoringStatus status) throws CoreException {
1105 		Assert.isNotNull(monitor);
1106 		Assert.isNotNull(status);
1107 		try {
1108 			monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, 24);
1109 			final ICompilationUnit source= getDeclaringType().getCompilationUnit();
1110 			final IType destination= getDestinationType();
1111 			final ICompilationUnit target= destination.getCompilationUnit();
1112 			final CompilationUnitRewrite sourceRewriter= getCompilationUnitRewrite(fCompilationUnitRewrites, source);
1113 			final CompilationUnitRewrite targetRewriter= getCompilationUnitRewrite(fCompilationUnitRewrites, target);
1114 			final Map<ICompilationUnit, ArrayList<IMember>> deleteMap= createMembersToDeleteMap(new SubProgressMonitor(monitor, 1));
1115 			final Map<ICompilationUnit, ArrayList<IType>> affectedMap= createAffectedTypesMap(new SubProgressMonitor(monitor, 1));
1116 			final ICompilationUnit[] units= getAffectedCompilationUnits(new SubProgressMonitor(monitor, 1));
1117 
1118 			final Map<IMember, IncomingMemberVisibilityAdjustment> adjustments= new HashMap<>();
1119 			MemberVisibilityAdjustor adjustor= null;
1120 			final IProgressMonitor sub= new SubProgressMonitor(monitor, 1);
1121 			try {
1122 				sub.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, units.length * 11);
1123 				for (ICompilationUnit unit : units) {
1124 					if (!source.equals(unit)
1125 							&& !target.equals(unit)
1126 							&& !deleteMap.containsKey(unit)
1127 							&& !affectedMap.containsKey(unit)) {
1128 						sub.worked(10);
1129 						continue;
1130 					}
1131 					CompilationUnitRewrite rewrite= getCompilationUnitRewrite(fCompilationUnitRewrites, unit);
1132 					if (deleteMap.containsKey(unit)) {
1133 						LinkedList<IMember> list= new LinkedList<>(deleteMap.get(unit));
1134 						if (destination.isInterface()) {
1135 							for (final Iterator<IMember> iterator= list.iterator(); iterator.hasNext();) {
1136 								final IMember member= iterator.next();
1137 								if (member instanceof IMethod)
1138 									iterator.remove();
1139 							}
1140 						}
1141 						deleteDeclarationNodes(sourceRewriter, sourceRewriter.getCu().equals(targetRewriter.getCu()), rewrite, list, SET_PULL_UP);
1142 					}
1143 					final CompilationUnit root= sourceRewriter.getRoot();
1144 					if (unit.equals(target)) {
1145 						final ASTRewrite rewriter= rewrite.getASTRewrite();
1146 						if (!JdtFlags.isAbstract(destination) && !destination.isInterface() && getAbstractMethods().length > 0) {
1147 							final AbstractTypeDeclaration declaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(destination, rewrite.getRoot());
1148 							ModifierRewrite.create(rewriter, declaration).setModifiers(declaration.getModifiers() | Modifier.ABSTRACT, rewrite.createCategorizedGroupDescription(RefactoringCoreMessages.PullUpRefactoring_make_target_abstract, SET_PULL_UP));
1149 						}
1150 						final TypeVariableMaplet[] mapping= TypeVariableUtil.subTypeToSuperType(getDeclaringType(), destination);
1151 						final IProgressMonitor subsub= new SubProgressMonitor(sub, 1);
1152 						final AbstractTypeDeclaration declaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(destination, rewrite.getRoot());
1153 						ImportRewriteContext context= new ContextSensitiveImportRewriteContext(declaration, rewrite.getImportRewrite());
1154 						fMembersToMove= JavaElementUtil.sortByOffset(fMembersToMove);
1155 						subsub.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, fMembersToMove.length);
1156 						IMember member= null;
1157 						for (int offset= fMembersToMove.length - 1; offset >= 0; offset--) {
1158 							member= fMembersToMove[offset];
1159 							adjustor= new MemberVisibilityAdjustor(destination, member);
1160 							adjustor.setRewrite(sourceRewriter.getASTRewrite(), root);
1161 
1162 							// TW: set to error if bug 78387 is fixed
1163 							adjustor.setFailureSeverity(RefactoringStatus.WARNING);
1164 
1165 							adjustor.setOwner(fOwner);
1166 							adjustor.setRewrites(fCompilationUnitRewrites);
1167 							adjustor.setStatus(status);
1168 							adjustor.setAdjustments(adjustments);
1169 							adjustor.adjustVisibility(new SubProgressMonitor(subsub, 1));
1170 							adjustments.remove(member);
1171 							if (member instanceof IField) {
1172 								final VariableDeclarationFragment oldField= ASTNodeSearchUtil.getFieldDeclarationFragmentNode((IField) member, root);
1173 								if (oldField != null) {
1174 									int flags= getModifiersWithUpdatedVisibility(member, member.getFlags(), adjustments, new SubProgressMonitor(subsub, 1), true, status);
1175 									final FieldDeclaration newField= createNewFieldDeclarationNode(rewriter, root, (IField) member, oldField, mapping, new SubProgressMonitor(subsub, 1), status, flags);
1176 									rewriter.getListRewrite(declaration, declaration.getBodyDeclarationsProperty()).insertAt(newField, org.eclipse.jdt.internal.corext.dom.BodyDeclarationRewrite.getInsertionIndex(newField, declaration.bodyDeclarations()), rewrite.createCategorizedGroupDescription(RefactoringCoreMessages.HierarchyRefactoring_add_member, SET_PULL_UP));
1177 									ImportRewriteUtil.addImports(rewrite, context, oldField.getParent(), new HashMap<Name, String>(), new HashMap<Name, String>(), false);
1178 
1179 									if (oldField.getParent() instanceof FieldDeclaration) {
1180 										// set fully qualified type name for pulled up types
1181 										FieldDeclaration vds= (FieldDeclaration) oldField.getParent();
1182 										ITypeBinding oldTypeBinding= vds.getType().resolveBinding();
1183 										if (oldTypeBinding == null || oldTypeBinding.isPrimitive()) {
1184 											continue; // no qualified types for primitives
1185 										}
1186 										String sourcePackage= oldTypeBinding.getPackage() == null ? "" : oldTypeBinding.getPackage().getName(); //$NON-NLS-1$
1187 										String targetPackage= targetRewriter.getRoot().getPackage() == null ? "" : targetRewriter.getRoot().getPackage().getName().toString(); //$NON-NLS-1$
1188 										String targetTypeBinding= targetPackage + "." + oldTypeBinding.getName(); //$NON-NLS-1$
1189 
1190 										// Find the same type-name field but fully qualified.
1191 										// In that case it won't shadow the pulled up field
1192 										boolean qualifiedTypeNameInTarget= true;
1193 										String sourceSignature= ((IField) member).getTypeSignature();
1194 										for (IField targetField : fDestinationType.getFields()) {
1195 											if (sourceSignature.equals(targetField.getTypeSignature())) {
1196 												qualifiedTypeNameInTarget= false;
1197 												break;
1198 											}
1199 										}
1200 										//check if same type name is accessible in new package (targetPackage + <type>)
1201 										IType findTargetType= target.getJavaProject().findType(targetTypeBinding);
1202 										if (!qualifiedTypeNameInTarget && findTargetType != null) {
1203 											if (sourcePackage.isEmpty() ^ targetPackage.isEmpty()) {
1204 												// not one package can be default package, either none or both
1205 												status.merge(RefactoringStatus.createErrorStatus(Messages.format(RefactoringCoreMessages.PullUpRefactoring_moving_fromto_default_package,
1206 														new String[] { JavaElementLabels.getTextLabel(member, JavaElementLabels.ALL_FULLY_QUALIFIED) }), JavaStatusContext.create(member)));
1207 											}
1208 
1209 											if (!sourcePackage.isEmpty()) {
1210 												Name newName= rewrite.getAST().newName(sourcePackage);
1211 												SimpleName newSimpleName= rewrite.getAST().newSimpleName(oldTypeBinding.getName());
1212 												SimpleType newSimpleType= null;
1213 												if (targetPackage.equals(sourcePackage)) {
1214 													// if source type is in same package as target then we don't need the fully qualified name
1215 													newSimpleType= rewrite.getAST().newSimpleType(newSimpleName);
1216 												} else {
1217 													QualifiedName newQualifiedTypeName= rewrite.getAST().newQualifiedName(newName, newSimpleName);
1218 													newSimpleType= rewrite.getAST().newSimpleType(newQualifiedTypeName);
1219 												}
1220 												newField.setType(newSimpleType);
1221 											}
1222 										}
1223 									}
1224 								}
1225 							} else if (member instanceof IMethod) {
1226 								final MethodDeclaration oldMethod= ASTNodeSearchUtil.getMethodDeclarationNode((IMethod) member, root);
1227 								if (oldMethod != null) {
1228 									if (JdtFlags.isStatic(member) && fDestinationType.isInterface())
1229 										status.merge(RefactoringStatus.createErrorStatus(Messages.format(RefactoringCoreMessages.PullUpRefactoring_moving_static_method_to_interface, new String[] { JavaElementLabels.getTextLabel(member, JavaElementLabels.ALL_FULLY_QUALIFIED)}), JavaStatusContext.create(member)));
1230 									final MethodDeclaration newMethod= createNewMethodDeclarationNode(sourceRewriter, rewrite, ((IMethod) member), oldMethod, mapping, adjustments, new SubProgressMonitor(subsub, 1), status);
1231 									rewriter.getListRewrite(declaration, declaration.getBodyDeclarationsProperty()).insertAt(newMethod, org.eclipse.jdt.internal.corext.dom.BodyDeclarationRewrite.getInsertionIndex(newMethod, declaration.bodyDeclarations()), rewrite.createCategorizedGroupDescription(RefactoringCoreMessages.HierarchyRefactoring_add_member, SET_PULL_UP));
1232 									ImportRewriteUtil.addImports(rewrite, context, oldMethod, new HashMap<Name, String>(), new HashMap<Name, String>(), newMethod.getBody() == null);
1233 								}
1234 							} else if (member instanceof IType) {
1235 								final AbstractTypeDeclaration oldType= ASTNodeSearchUtil.getAbstractTypeDeclarationNode((IType) member, root);
1236 								if (oldType != null) {
1237 									final BodyDeclaration newType= createNewTypeDeclarationNode(((IType) member), oldType, root, mapping, rewriter);
1238 									rewriter.getListRewrite(declaration, declaration.getBodyDeclarationsProperty()).insertAt(newType, org.eclipse.jdt.internal.corext.dom.BodyDeclarationRewrite.getInsertionIndex(newType, declaration.bodyDeclarations()), rewrite.createCategorizedGroupDescription(RefactoringCoreMessages.HierarchyRefactoring_add_member, SET_PULL_UP));
1239 									ImportRewriteUtil.addImports(rewrite, context, oldType, new HashMap<Name, String>(), new HashMap<Name, String>(), false);
1240 								}
1241 							} else
1242 								Assert.isTrue(false);
1243 							subsub.worked(1);
1244 						}
1245 						subsub.done();
1246 						for (IMethod abstractMethod : fAbstractMethods)
1247 							createAbstractMethod(abstractMethod, sourceRewriter, root, declaration, mapping, rewrite, adjustments, new SubProgressMonitor(sub, 1), status);
1248 					} else
1249 						sub.worked(2);
1250 					if (unit.equals(sourceRewriter.getCu())) {
1251 						final IProgressMonitor subsub= new SubProgressMonitor(sub, 1);
1252 						subsub.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, fAbstractMethods.length * 2);
1253 						for (IMethod method : fAbstractMethods) {
1254 							adjustor= new MemberVisibilityAdjustor(destination, method);
1255 							adjustor.setRewrite(sourceRewriter.getASTRewrite(), root);
1256 							adjustor.setRewrites(fCompilationUnitRewrites);
1257 
1258 							// TW: set to error if bug 78387 is fixed
1259 							adjustor.setFailureSeverity(RefactoringStatus.WARNING);
1260 
1261 							adjustor.setOwner(fOwner);
1262 							adjustor.setStatus(status);
1263 							adjustor.setAdjustments(adjustments);
1264 							if (destination.isInterface() && !JdtFlags.isPublic(method)) {
1265 								adjustments.put(method, new MemberVisibilityAdjustor.OutgoingMemberVisibilityAdjustment(method, Modifier.ModifierKeyword.PUBLIC_KEYWORD, RefactoringStatus.createWarningStatus(Messages.format(RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_method_warning, new String[] { MemberVisibilityAdjustor.getLabel(method), RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_public}), JavaStatusContext.create(method))));
1266 							} else if (needsVisibilityAdjustment(method, false, new SubProgressMonitor(subsub, 1), status)) {
1267 								adjustments.put(method, new MemberVisibilityAdjustor.OutgoingMemberVisibilityAdjustment(method, Modifier.ModifierKeyword.PROTECTED_KEYWORD, RefactoringStatus.createWarningStatus(Messages.format(RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_method_warning, new String[] { MemberVisibilityAdjustor.getLabel(method), RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_protected}), JavaStatusContext.create(method))));
1268 							}
1269 						}
1270 					} else
1271 						sub.worked(2);
1272 					if (affectedMap.containsKey(unit))
1273 						addNecessaryMethodStubs(affectedMap.get(unit), root, rewrite, adjustments, new SubProgressMonitor(sub, 2), status);
1274 					if (sub.isCanceled())
1275 						throw new OperationCanceledException();
1276 				}
1277 			} finally {
1278 				sub.done();
1279 			}
1280 			if (adjustor != null && !adjustments.isEmpty())
1281 				adjustor.rewriteVisibility(new SubProgressMonitor(monitor, 1));
1282 			final TextEditBasedChangeManager manager= new TextEditBasedChangeManager();
1283 			if (fReplace) {
1284 				final Set<Entry<ICompilationUnit, CompilationUnitRewrite>> entrySet= fCompilationUnitRewrites.entrySet();
1285 				for (final Entry<ICompilationUnit, CompilationUnitRewrite> entry : entrySet) {
1286 					ICompilationUnit unit= entry.getKey();
1287 					CompilationUnitRewrite rewrite= entry.getValue();
1288 					if (rewrite != null) {
1289 						final CompilationUnitChange change= rewrite.createChange(false);
1290 						if (change != null)
1291 							manager.manage(unit, change);
1292 					}
1293 				}
1294 				TextEdit edit= null;
1295 				TextEditBasedChange change= null;
1296 				final Map<ICompilationUnit, ICompilationUnit> workingcopies= new HashMap<>();
1297 				final IProgressMonitor subMonitor= new SubProgressMonitor(monitor, 1);
1298 				try {
1299 					subMonitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, entrySet.size());
1300 					for (final Entry<ICompilationUnit, CompilationUnitRewrite> entry : entrySet) {
1301 						ICompilationUnit unit= entry.getKey();
1302 						change= manager.get(unit);
1303 						if (change instanceof TextChange) {
1304 							edit= ((TextChange) change).getEdit();
1305 							if (edit != null) {
1306 								final ICompilationUnit copy= createWorkingCopy(unit, edit, status, new SubProgressMonitor(monitor, 1));
1307 								if (copy != null)
1308 									workingcopies.put(unit, copy);
1309 							}
1310 						}
1311 					}
1312 					final ICompilationUnit current= workingcopies.get(sourceRewriter.getCu());
1313 					if (current != null)
1314 						rewriteTypeOccurrences(manager, sourceRewriter, current, new HashSet<String>(), status, new SubProgressMonitor(monitor, 16));
1315 				} finally {
1316 					subMonitor.done();
1317 					for (ICompilationUnit unit : manager.getAllCompilationUnits()) {
1318 						CompilationUnitChange current= (CompilationUnitChange) manager.get(unit);
1319 						if (change != null && current.getEdit() == null)
1320 							manager.remove(unit);
1321 					}
1322 				}
1323 			}
1324 			registerChanges(manager);
1325 			return manager;
1326 		} finally {
1327 			fCompilationUnitRewrites.clear();
1328 			monitor.done();
1329 		}
1330 	}
1331 
createAffectedTypesMap(final IProgressMonitor monitor)1332 	private Map<ICompilationUnit, ArrayList<IType>> createAffectedTypesMap(final IProgressMonitor monitor) throws JavaModelException {
1333 		if (!fCreateMethodStubs || (getAbstractMethods().length <= 0))
1334 			return new HashMap<>(0);
1335 		final Set<IType> affected= getAffectedSubTypes(getDestinationTypeHierarchy(monitor), getDestinationType());
1336 		final Map<ICompilationUnit, ArrayList<IType>> result= new HashMap<>();
1337 		for (IType type : affected) {
1338 			final ICompilationUnit unit= type.getCompilationUnit();
1339 			if (!result.containsKey(unit))
1340 				result.put(unit, new ArrayList<IType>(1));
1341 			result.get(unit).add(type);
1342 		}
1343 		return result;
1344 	}
1345 
createJavadocForStub(final String enclosingTypeName, final MethodDeclaration oldMethod, final MethodDeclaration newMethodNode, final ICompilationUnit cu, final ASTRewrite rewrite)1346 	private Javadoc createJavadocForStub(final String enclosingTypeName, final MethodDeclaration oldMethod, final MethodDeclaration newMethodNode, final ICompilationUnit cu, final ASTRewrite rewrite) throws CoreException {
1347 		if (fSettings.createComments) {
1348 			final IMethodBinding binding= oldMethod.resolveBinding();
1349 			if (binding != null) {
1350 				final ITypeBinding[] params= binding.getParameterTypes();
1351 				final String fullTypeName= getDestinationType().getFullyQualifiedName('.');
1352 				final String[] fullParamNames= new String[params.length];
1353 				for (int i= 0; i < fullParamNames.length; i++) {
1354 					fullParamNames[i]= Bindings.getFullyQualifiedName(params[i]);
1355 				}
1356 				final String comment= CodeGeneration.getMethodComment(cu, enclosingTypeName, newMethodNode, false, binding.getName(), fullTypeName, fullParamNames, StubUtility.getLineDelimiterUsed(cu));
1357 				if (comment != null)
1358 					return (Javadoc) rewrite.createStringPlaceholder(comment, ASTNode.JAVADOC);
1359 			}
1360 		}
1361 		return null;
1362 	}
1363 
createMembersToDeleteMap(final IProgressMonitor monitor)1364 	private Map<ICompilationUnit, ArrayList<IMember>> createMembersToDeleteMap(final IProgressMonitor monitor) throws JavaModelException {
1365 		final Map<ICompilationUnit, ArrayList<IMember>> result= new HashMap<>();
1366 		for (final IMember member : getMembersToDelete(monitor)) {
1367 			final ICompilationUnit cu= member.getCompilationUnit();
1368 			if (!result.containsKey(cu))
1369 				result.put(cu, new ArrayList<IMember>(1));
1370 			result.get(cu).add(member);
1371 		}
1372 		return result;
1373 	}
1374 
createNewMethodDeclarationNode(final CompilationUnitRewrite sourceRewrite, final CompilationUnitRewrite targetRewrite, final IMethod sourceMethod, final MethodDeclaration oldMethod, final TypeVariableMaplet[] mapping, final Map<IMember, IncomingMemberVisibilityAdjustment> adjustments, final IProgressMonitor monitor, final RefactoringStatus status)1375 	private MethodDeclaration createNewMethodDeclarationNode(final CompilationUnitRewrite sourceRewrite, final CompilationUnitRewrite targetRewrite, final IMethod sourceMethod, final MethodDeclaration oldMethod, final TypeVariableMaplet[] mapping, final Map<IMember, IncomingMemberVisibilityAdjustment> adjustments, final IProgressMonitor monitor, final RefactoringStatus status) throws JavaModelException {
1376 		final ASTRewrite rewrite= targetRewrite.getASTRewrite();
1377 		final AST ast= rewrite.getAST();
1378 		ITypeBinding destinationBinding= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(getDestinationType(), targetRewrite.getRoot()).resolveBinding();
1379 		StubUtility2Core.addOverrideAnnotation(fSettings, sourceMethod.getJavaProject(), sourceRewrite.getASTRewrite(), sourceRewrite.getImportRewrite(), oldMethod,
1380 				destinationBinding == null ? false : destinationBinding.isInterface(),
1381 				sourceRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.PullUpRefactoring_add_override_annotation, SET_PULL_UP));
1382 		final MethodDeclaration newMethod= ast.newMethodDeclaration();
1383 		if (!getDestinationType().isInterface())
1384 			copyBodyOfPulledUpMethod(sourceRewrite, targetRewrite, sourceMethod, oldMethod, newMethod, mapping, monitor);
1385 		newMethod.setConstructor(oldMethod.isConstructor());
1386 		copyExtraDimensions(oldMethod, newMethod);
1387 		copyJavadocNode(rewrite, oldMethod, newMethod);
1388 		int modifiers= getModifiersWithUpdatedVisibility(sourceMethod, sourceMethod.getFlags(), adjustments, monitor, true, status);
1389 		if (fDeletedMethods.length == 0 || getDestinationType().isInterface()) {
1390 			modifiers&= ~Flags.AccFinal;
1391 		}
1392 
1393 		if (oldMethod.isVarargs())
1394 			modifiers&= ~Flags.AccVarargs;
1395 		copyAnnotations(oldMethod, newMethod);
1396 		newMethod.modifiers().addAll(ASTNodeFactory.newModifiers(ast, modifiers));
1397 		newMethod.setName(((SimpleName) ASTNode.copySubtree(ast, oldMethod.getName())));
1398 		copyReturnType(rewrite, getDeclaringType().getCompilationUnit(), oldMethod, newMethod, mapping);
1399 		copyParameters(rewrite, getDeclaringType().getCompilationUnit(), oldMethod, newMethod, mapping);
1400 		copyThrownExceptions(oldMethod, newMethod);
1401 		copyTypeParameters(oldMethod, newMethod);
1402 		return newMethod;
1403 	}
1404 
createNewTypeDeclarationNode(final IType type, final AbstractTypeDeclaration oldType, final CompilationUnit declaringCuNode, final TypeVariableMaplet[] mapping, final ASTRewrite rewrite)1405 	private BodyDeclaration createNewTypeDeclarationNode(final IType type, final AbstractTypeDeclaration oldType, final CompilationUnit declaringCuNode, final TypeVariableMaplet[] mapping, final ASTRewrite rewrite) throws JavaModelException {
1406 		final ICompilationUnit declaringCu= getDeclaringType().getCompilationUnit();
1407 		if (!JdtFlags.isPublic(type) && !JdtFlags.isProtected(type)) {
1408 			if (mapping.length > 0)
1409 				return createPlaceholderForTypeDeclaration(oldType, declaringCu, mapping, rewrite, true);
1410 
1411 			return createPlaceholderForProtectedTypeDeclaration(oldType, declaringCuNode, declaringCu, rewrite, true);
1412 		}
1413 		if (mapping.length > 0)
1414 			return createPlaceholderForTypeDeclaration(oldType, declaringCu, mapping, rewrite, true);
1415 
1416 		return createPlaceholderForTypeDeclaration(oldType, declaringCu, rewrite, true);
1417 	}
1418 
createWorkingCopy(final ICompilationUnit unit, final TextEdit edit, final RefactoringStatus status, final IProgressMonitor monitor)1419 	private ICompilationUnit createWorkingCopy(final ICompilationUnit unit, final TextEdit edit, final RefactoringStatus status, final IProgressMonitor monitor) {
1420 		try {
1421 			monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, 1);
1422 			final ICompilationUnit copy= getSharedWorkingCopy(unit.getPrimary(), new SubProgressMonitor(monitor, 1));
1423 			final IDocument document= new Document(unit.getBuffer().getContents());
1424 			edit.apply(document, TextEdit.UPDATE_REGIONS);
1425 			copy.getBuffer().setContents(document.get());
1426 			JavaModelUtil.reconcile(copy);
1427 			return copy;
1428 		} catch (JavaModelException exception) {
1429 			status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_internal_error));
1430 		} catch (MalformedTreeException exception) {
1431 			status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_internal_error));
1432 		} catch (BadLocationException exception) {
1433 			status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_internal_error));
1434 		} finally {
1435 			monitor.done();
1436 		}
1437 		return null;
1438 	}
1439 
1440 	/**
1441 	 * Creates a working copy layer if necessary.
1442 	 *
1443 	 * @param monitor
1444 	 *            the progress monitor to use
1445 	 * @return a status describing the outcome of the operation
1446 	 */
createWorkingCopyLayer(IProgressMonitor monitor)1447 	protected RefactoringStatus createWorkingCopyLayer(IProgressMonitor monitor) {
1448 		try {
1449 			monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, 1);
1450 			ICompilationUnit unit= getDeclaringType().getCompilationUnit();
1451 			if (fLayer)
1452 				unit= unit.findWorkingCopy(fOwner);
1453 			resetWorkingCopies(unit);
1454 			return new RefactoringStatus();
1455 		} finally {
1456 			monitor.done();
1457 		}
1458 	}
1459 
getAbstractMethods()1460 	private IMethod[] getAbstractMethods() throws JavaModelException {
1461 		final IMethod[] toDeclareAbstract= fAbstractMethods;
1462 		final IMethod[] abstractPulledUp= getAbstractMethodsToPullUp();
1463 		final Set<IMember> result= new LinkedHashSet<>(toDeclareAbstract.length + abstractPulledUp.length + fMembersToMove.length);
1464 		if (fDestinationType.isInterface()) {
1465 			for (IMember element : fMembersToMove) {
1466 				if (element.getElementType() == IJavaElement.METHOD) {
1467 					result.add(element);
1468 				}
1469 			}
1470 		}
1471 		result.addAll(Arrays.asList(toDeclareAbstract));
1472 		result.addAll(Arrays.asList(abstractPulledUp));
1473 		return result.toArray(new IMethod[result.size()]);
1474 	}
1475 
getAbstractMethodsToPullUp()1476 	private IMethod[] getAbstractMethodsToPullUp() throws JavaModelException {
1477 		final List<IMember> result= new ArrayList<>(fMembersToMove.length);
1478 		for (final IMember member : fMembersToMove) {
1479 			if (member instanceof IMethod && JdtFlags.isAbstract(member))
1480 				result.add(member);
1481 		}
1482 		return result.toArray(new IMethod[result.size()]);
1483 	}
1484 
getAdditionalRequiredMembersToPullUp(final IProgressMonitor monitor)1485 	public IMember[] getAdditionalRequiredMembersToPullUp(final IProgressMonitor monitor) throws JavaModelException {
1486 		final IMember[] members= getCreatedDestinationMembers();
1487 		List<IMember> queue;
1488 		try {
1489 			monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_calculating_required, getDeclaringType().getChildren().length);// maximum
1490 			queue= new ArrayList<>(members.length);
1491 			queue.addAll(Arrays.asList(members));
1492 			if (queue.isEmpty())
1493 				return new IMember[0];
1494 			int i= 0;
1495 			IMember current;
1496 			do {
1497 				current= queue.get(i);
1498 				addAllRequiredPullableMembers(queue, current, new SubProgressMonitor(monitor, 1));
1499 				i++;
1500 				if (queue.size() == i)
1501 					current= null;
1502 			} while (current != null);
1503 			queue.removeAll(Arrays.asList(members));// report only additional
1504 		} finally {
1505 			monitor.done();
1506 		}
1507 		return queue.toArray(new IMember[queue.size()]);
1508 	}
1509 
getAffectedCompilationUnits(final IProgressMonitor monitor)1510 	private ICompilationUnit[] getAffectedCompilationUnits(final IProgressMonitor monitor) throws JavaModelException {
1511 		final IType[] allSubtypes= getDestinationTypeHierarchy(monitor).getAllSubtypes(getDestinationType());
1512 		final Set<ICompilationUnit> result= new HashSet<>(allSubtypes.length);
1513 		for (IType subtype : allSubtypes) {
1514 			ICompilationUnit cu= subtype.getCompilationUnit();
1515 			if (cu != null)
1516 				result.add(cu);
1517 		}
1518 		result.add(getDestinationType().getCompilationUnit());
1519 		return result.toArray(new ICompilationUnit[result.size()]);
1520 	}
1521 
getCandidateTypes(final RefactoringStatus status, final IProgressMonitor monitor)1522 	public IType[] getCandidateTypes(final RefactoringStatus status, final IProgressMonitor monitor) throws JavaModelException {
1523 		final IType declaring= getDeclaringType();
1524 		final IType[] superTypes= declaring.newSupertypeHierarchy(fOwner, monitor).getAllSupertypes(declaring);
1525 		final List<IType> list= new ArrayList<>(superTypes.length);
1526 		int binary= 0;
1527 		for (final IType type : superTypes) {
1528 			if (type != null && type.exists() && !type.isReadOnly() && !type.isBinary() && !"java.lang.Object".equals(type.getFullyQualifiedName())) { //$NON-NLS-1$
1529 				list.add(type);
1530 			} else {
1531 				if (type != null && type.isBinary()) {
1532 					binary++;
1533 				}
1534 			}
1535 		}
1536 		if (superTypes.length == 1 && superTypes[0].getFullyQualifiedName().equals("java.lang.Object")) //$NON-NLS-1$
1537 			status.addFatalError(RefactoringCoreMessages.PullUPRefactoring_not_java_lang_object);
1538 		else if (superTypes.length == binary)
1539 			status.addFatalError(RefactoringCoreMessages.PullUPRefactoring_no_all_binary);
1540 
1541 		Collections.reverse(list);
1542 		return list.toArray(new IType[list.size()]);
1543 	}
1544 
getCompilationUnitRewrite(final Map<ICompilationUnit, CompilationUnitRewrite> rewrites, final ICompilationUnit unit)1545 	protected CompilationUnitRewrite getCompilationUnitRewrite(final Map<ICompilationUnit, CompilationUnitRewrite> rewrites, final ICompilationUnit unit) {
1546 		Assert.isNotNull(rewrites);
1547 		Assert.isNotNull(unit);
1548 		CompilationUnitRewrite rewrite= rewrites.get(unit);
1549 		if (rewrite == null) {
1550 			rewrite= new CompilationUnitRewrite(fOwner, unit);
1551 			rewrites.put(unit, rewrite);
1552 		}
1553 		return rewrite;
1554 	}
1555 
getCreatedDestinationMembers()1556 	private IMember[] getCreatedDestinationMembers() {
1557 		final List<IMember> result= new ArrayList<>(fMembersToMove.length + fAbstractMethods.length);
1558 		result.addAll(Arrays.asList(fMembersToMove));
1559 		result.addAll(Arrays.asList(fAbstractMethods));
1560 		return result.toArray(new IMember[result.size()]);
1561 	}
1562 
getCreateMethodStubs()1563 	public boolean getCreateMethodStubs() {
1564 		return fCreateMethodStubs;
1565 	}
1566 
getDeclaringSuperTypeHierarchy(final IProgressMonitor monitor)1567 	public ITypeHierarchy getDeclaringSuperTypeHierarchy(final IProgressMonitor monitor) throws JavaModelException {
1568 		try {
1569 			if (fCachedDeclaringSuperTypeHierarchy != null)
1570 				return fCachedDeclaringSuperTypeHierarchy;
1571 			fCachedDeclaringSuperTypeHierarchy= getDeclaringType().newSupertypeHierarchy(fOwner, monitor);
1572 			return fCachedDeclaringSuperTypeHierarchy;
1573 		} finally {
1574 			monitor.done();
1575 		}
1576 	}
1577 
getDestinationType()1578 	public IType getDestinationType() {
1579 		return fDestinationType;
1580 	}
1581 
getDestinationTypeHierarchy(final IProgressMonitor monitor)1582 	public ITypeHierarchy getDestinationTypeHierarchy(final IProgressMonitor monitor) throws JavaModelException {
1583 		try {
1584 			if (fCachedDestinationTypeHierarchy != null && fCachedDestinationTypeHierarchy.getType().equals(getDestinationType()))
1585 				return fCachedDestinationTypeHierarchy;
1586 			fCachedDestinationTypeHierarchy= getDestinationType().newTypeHierarchy(fOwner, monitor);
1587 			return fCachedDestinationTypeHierarchy;
1588 		} finally {
1589 			monitor.done();
1590 		}
1591 	}
1592 
1593 	@Override
getElements()1594 	public Object[] getElements() {
1595 		return fMembersToMove;
1596 	}
1597 
1598 	@Override
getIdentifier()1599 	public String getIdentifier() {
1600 		return IDENTIFIER;
1601 	}
1602 
getMatchingElements(final IProgressMonitor monitor, final boolean includeAbstract)1603 	public IMember[] getMatchingElements(final IProgressMonitor monitor, final boolean includeAbstract) throws JavaModelException {
1604 		try {
1605 			final Set<IMember> result= new HashSet<>();
1606 			final IType destination= getDestinationType();
1607 			final Map<IMember, Set<IMember>> matching= getMatchingMembers(getDestinationTypeHierarchy(monitor), getDestinationType(), includeAbstract);
1608 			for (Entry<IMember, Set<IMember>> entry : matching.entrySet()) {
1609 				IMember key= entry.getKey();
1610 				Assert.isTrue(!key.getDeclaringType().equals(destination));
1611 				result.addAll(entry.getValue());
1612 			}
1613 			return result.toArray(new IMember[result.size()]);
1614 		} finally {
1615 			monitor.done();
1616 		}
1617 	}
1618 
getMatchingMembers(final ITypeHierarchy hierarchy, final IType type, final boolean includeAbstract)1619 	private Map<IMember, Set<IMember>> getMatchingMembers(final ITypeHierarchy hierarchy, final IType type, final boolean includeAbstract) throws JavaModelException {
1620 		final Map<IMember, Set<IMember>> result= new HashMap<>();
1621 		result.putAll(getMatchingMembersMapping(type));
1622 		for (IType subType : hierarchy.getAllSubtypes(type)) {
1623 			final Map<IMember, Set<IMember>> map= getMatchingMembersMapping(subType);
1624 			mergeMaps(result, map);
1625 			upgradeMap(result, map);
1626 		}
1627 		if (includeAbstract)
1628 			return result;
1629 
1630 		for (IMethod abstractMethod : fAbstractMethods) {
1631 			if (result.containsKey(abstractMethod))
1632 				result.remove(abstractMethod);
1633 		}
1634 		return result;
1635 	}
1636 
getMatchingMembersMapping(final IType initial)1637 	private Map<IMember, Set<IMember>> getMatchingMembersMapping(final IType initial) throws JavaModelException {
1638 		final Map<IMember, Set<IMember>> result= new HashMap<>();
1639 		for (final IMember member : getCreatedDestinationMembers()) {
1640 			if (member instanceof IMethod) {
1641 				final IMethod method= (IMethod) member;
1642 				final IMethod found= MemberCheckUtil.findMethod(method, initial.getMethods());
1643 				if (found != null)
1644 					addMatchingMember(result, method, found);
1645 			} else if (member instanceof IField) {
1646 				final IField field= (IField) member;
1647 				final IField found= initial.getField(field.getElementName());
1648 				if (found.exists() && field.getTypeSignature().equals(found.getTypeSignature())) {
1649 					addMatchingMember(result, field, found);
1650 				}
1651 			} else if (member instanceof IType) {
1652 				final IType type= (IType) member;
1653 				final IType found= initial.getType(type.getElementName());
1654 				if (found.exists())
1655 					addMatchingMember(result, type, found);
1656 			} else
1657 				Assert.isTrue(false);
1658 		}
1659 
1660 		return result;
1661 	}
1662 
getMembersToDelete(final IProgressMonitor monitor)1663 	private IMember[] getMembersToDelete(final IProgressMonitor monitor) throws JavaModelException {
1664 		try {
1665 			final IMember[] typesToDelete= getMembers(fMembersToMove, IJavaElement.TYPE);
1666 			final IMember[] matchingElements= getMatchingElements(monitor, false);
1667 			final IMember[] matchingFields= getMembers(matchingElements, IJavaElement.FIELD);
1668 
1669 			List<IMember> toDelete= new ArrayList<>();
1670 			IMember[] all= JavaElementUtil.merge(matchingFields, typesToDelete);
1671 
1672 			toDelete.addAll(Arrays.asList(fMembersToMove));
1673 			toDelete.retainAll(Arrays.asList(all));
1674 
1675 			return JavaElementUtil.merge(toDelete.toArray(new IMember[0]), fDeletedMethods);
1676 		} finally {
1677 			monitor.done();
1678 		}
1679 	}
1680 
getModifiersWithUpdatedVisibility(final IMember member, final int modifiers, final Map<IMember, IncomingMemberVisibilityAdjustment> adjustments, final IProgressMonitor monitor, final boolean considerReferences, final RefactoringStatus status)1681 	private int getModifiersWithUpdatedVisibility(final IMember member, final int modifiers, final Map<IMember, IncomingMemberVisibilityAdjustment> adjustments, final IProgressMonitor monitor, final boolean considerReferences, final RefactoringStatus status) throws JavaModelException {
1682 		if (getDestinationType().isInterface()) {
1683 			int flags= JdtFlags.clearAccessModifiers(modifiers);
1684 			flags= JdtFlags.clearFlag(Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL, flags);
1685 			return flags;
1686 		}
1687 		if (needsVisibilityAdjustment(member, considerReferences, monitor, status)) {
1688 			final MemberVisibilityAdjustor.OutgoingMemberVisibilityAdjustment adjustment= new MemberVisibilityAdjustor.OutgoingMemberVisibilityAdjustment(member, Modifier.ModifierKeyword.PROTECTED_KEYWORD, RefactoringStatus.createWarningStatus(Messages.format(MemberVisibilityAdjustor.getMessage(member), new String[] { MemberVisibilityAdjustor.getLabel(member), MemberVisibilityAdjustor.getLabel(Modifier.ModifierKeyword.PROTECTED_KEYWORD)})));
1689 			adjustment.setNeedsRewriting(false);
1690 			adjustments.put(member, adjustment);
1691 			return JdtFlags.clearAccessModifiers(modifiers) | Modifier.PROTECTED;
1692 		}
1693 		return modifiers;
1694 	}
1695 
getNotDeletedMembers(final IProgressMonitor monitor)1696 	private Set<IMember> getNotDeletedMembers(final IProgressMonitor monitor) throws JavaModelException {
1697 		final Set<IMember> matchingSet= new HashSet<>();
1698 		monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, 2);
1699 		matchingSet.addAll(Arrays.asList(getMatchingElements(new SubProgressMonitor(monitor, 1), true)));
1700 		matchingSet.removeAll(Arrays.asList(getMembersToDelete(new SubProgressMonitor(monitor, 1))));
1701 		monitor.done();
1702 		return matchingSet;
1703 	}
1704 
1705 	@Override
getProcessorName()1706 	public String getProcessorName() {
1707 		return RefactoringCoreMessages.PullUpRefactoring_Pull_Up;
1708 	}
1709 
getPullableMembersOfDeclaringType()1710 	public IMember[] getPullableMembersOfDeclaringType() {
1711 		try {
1712 			return RefactoringAvailabilityTester.getPullUpMembers(getDeclaringType());
1713 		} catch (JavaModelException e) {
1714 			return new IMember[0];
1715 		}
1716 	}
1717 
1718 	// skipped super classes are those declared in the hierarchy between the
1719 	// declaring type of the selected members
1720 	// and the target type
getSkippedSuperTypes(final IProgressMonitor monitor)1721 	private Set<IType> getSkippedSuperTypes(final IProgressMonitor monitor) throws JavaModelException {
1722 		monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, 1);
1723 		try {
1724 			if (fCachedSkippedSuperTypes != null && getDestinationTypeHierarchy(new SubProgressMonitor(monitor, 1)).getType().equals(getDestinationType()))
1725 				return fCachedSkippedSuperTypes;
1726 			final ITypeHierarchy hierarchy= getDestinationTypeHierarchy(new SubProgressMonitor(monitor, 1));
1727 			fCachedSkippedSuperTypes= new HashSet<>(2);
1728 			IType current= hierarchy.getSuperclass(getDeclaringType());
1729 			while (current != null && !current.equals(getDestinationType())) {
1730 				fCachedSkippedSuperTypes.add(current);
1731 				current= hierarchy.getSuperclass(current);
1732 			}
1733 			return fCachedSkippedSuperTypes;
1734 		} finally {
1735 			monitor.done();
1736 		}
1737 	}
1738 
initialize(final JavaRefactoringArguments extended)1739 	private RefactoringStatus initialize(final JavaRefactoringArguments extended) {
1740 		String handle= extended.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT);
1741 		if (handle != null) {
1742 			final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(extended.getProject(), handle, false);
1743 			if (element == null || !element.exists() || element.getElementType() != IJavaElement.TYPE)
1744 				return JavaRefactoringDescriptorUtil.createInputFatalStatus(element, getProcessorName(), IJavaRefactorings.PULL_UP);
1745 			else
1746 				fDestinationType= (IType) element;
1747 		} else
1748 			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT));
1749 		final String stubs= extended.getAttribute(ATTRIBUTE_STUBS);
1750 		if (stubs != null) {
1751 			fCreateMethodStubs= Boolean.parseBoolean(stubs);
1752 		} else
1753 			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_STUBS));
1754 		final String instance= extended.getAttribute(ATTRIBUTE_INSTANCEOF);
1755 		if (instance != null) {
1756 			fInstanceOf= Boolean.parseBoolean(instance);
1757 		} else
1758 			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_INSTANCEOF));
1759 		final String replace= extended.getAttribute(ATTRIBUTE_REPLACE);
1760 		if (replace != null) {
1761 			fReplace= Boolean.parseBoolean(replace);
1762 		} else
1763 			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_REPLACE));
1764 		int pullCount= 0;
1765 		int abstractCount= 0;
1766 		int deleteCount= 0;
1767 		String value= extended.getAttribute(ATTRIBUTE_ABSTRACT);
1768 		if (value != null && !"".equals(value)) {//$NON-NLS-1$
1769 			try {
1770 				abstractCount= Integer.parseInt(value);
1771 			} catch (NumberFormatException exception) {
1772 				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_ABSTRACT));
1773 			}
1774 		} else
1775 			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_ABSTRACT));
1776 		value= extended.getAttribute(ATTRIBUTE_DELETE);
1777 		if (value != null && !"".equals(value)) {//$NON-NLS-1$
1778 			try {
1779 				deleteCount= Integer.parseInt(value);
1780 			} catch (NumberFormatException exception) {
1781 				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_DELETE));
1782 			}
1783 		} else
1784 			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_DELETE));
1785 		value= extended.getAttribute(ATTRIBUTE_PULL);
1786 		if (value != null && !"".equals(value)) {//$NON-NLS-1$
1787 			try {
1788 				pullCount= Integer.parseInt(value);
1789 			} catch (NumberFormatException exception) {
1790 				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_PULL));
1791 			}
1792 		} else
1793 			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_PULL));
1794 		final RefactoringStatus status= new RefactoringStatus();
1795 		List<IJavaElement> elements= new ArrayList<>();
1796 		for (int index= 0; index < pullCount; index++) {
1797 			final String attribute= JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + (index + 1);
1798 			handle= extended.getAttribute(attribute);
1799 			if (handle != null && !"".equals(handle)) { //$NON-NLS-1$
1800 				final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(extended.getProject(), handle, false);
1801 				if (element == null || !element.exists())
1802 					status.merge(JavaRefactoringDescriptorUtil.createInputWarningStatus(element, getProcessorName(), IJavaRefactorings.PULL_UP));
1803 				else
1804 					elements.add(element);
1805 			} else
1806 				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, attribute));
1807 		}
1808 		fMembersToMove= elements.toArray(new IMember[elements.size()]);
1809 		elements= new ArrayList<>();
1810 		for (int index= 0; index < deleteCount; index++) {
1811 			final String attribute= JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + (pullCount + index + 1);
1812 			handle= extended.getAttribute(attribute);
1813 			if (handle != null && !"".equals(handle)) { //$NON-NLS-1$
1814 				final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(extended.getProject(), handle, false);
1815 				if (element == null || !element.exists())
1816 					status.merge(JavaRefactoringDescriptorUtil.createInputWarningStatus(element, getProcessorName(), IJavaRefactorings.PULL_UP));
1817 				else
1818 					elements.add(element);
1819 			} else
1820 				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, attribute));
1821 		}
1822 		fDeletedMethods= elements.toArray(new IMethod[elements.size()]);
1823 		elements= new ArrayList<>();
1824 		for (int index= 0; index < abstractCount; index++) {
1825 			final String attribute= JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + (pullCount + abstractCount + index + 1);
1826 			handle= extended.getAttribute(attribute);
1827 			if (handle != null && !"".equals(handle)) { //$NON-NLS-1$
1828 				final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(extended.getProject(), handle, false);
1829 				if (element == null || !element.exists())
1830 					status.merge(JavaRefactoringDescriptorUtil.createInputWarningStatus(element, getProcessorName(), IJavaRefactorings.PULL_UP));
1831 				else
1832 					elements.add(element);
1833 			} else
1834 				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, attribute));
1835 		}
1836 		fAbstractMethods= elements.toArray(new IMethod[elements.size()]);
1837 		IJavaProject project= null;
1838 		if (fMembersToMove.length > 0)
1839 			project= fMembersToMove[0].getJavaProject();
1840 		fSettings= JavaPreferencesSettings.getCodeGenerationSettings(project);
1841 		if (!status.isOK())
1842 			return status;
1843 		return new RefactoringStatus();
1844 	}
1845 
1846 	@Override
isApplicable()1847 	public boolean isApplicable() throws CoreException {
1848 		return RefactoringAvailabilityTester.isPullUpAvailable(fMembersToMove);
1849 	}
1850 
isAvailableInDestination(final IMethod method, final IProgressMonitor monitor)1851 	private boolean isAvailableInDestination(final IMethod method, final IProgressMonitor monitor) throws JavaModelException {
1852 		try {
1853 			final IType destination= getDestinationType();
1854 			final IMethod first= JavaModelUtil.findMethod(method.getElementName(), method.getParameterTypes(), false, destination);
1855 			if (first != null && MethodChecks.isVirtual(first))
1856 				return true;
1857 			final ITypeHierarchy hierarchy= getDestinationTypeHierarchy(monitor);
1858 			final IMethod found= JavaModelUtil.findMethodInHierarchy(hierarchy, destination, method.getElementName(), method.getParameterTypes(), false);
1859 			return found != null && MethodChecks.isVirtual(found);
1860 		} finally {
1861 			monitor.done();
1862 		}
1863 	}
1864 
isRequiredPullableMember(final List<IMember> queue, final IMember member)1865 	private boolean isRequiredPullableMember(final List<IMember> queue, final IMember member) throws JavaModelException {
1866 		final IType declaring= member.getDeclaringType();
1867 		if (declaring == null) // not a member
1868 			return false;
1869 		return declaring.equals(getDeclaringType()) && !queue.contains(member) && RefactoringAvailabilityTester.isPullUpAvailable(member);
1870 	}
1871 
registerChanges(final TextEditBasedChangeManager manager)1872 	protected void registerChanges(final TextEditBasedChangeManager manager) throws CoreException {
1873 		for (final Entry<ICompilationUnit, CompilationUnitRewrite> entry : fCompilationUnitRewrites.entrySet()) {
1874 			CompilationUnitRewrite rewrite= entry.getValue();
1875 			if (rewrite != null) {
1876 				final CompilationUnitChange change= rewrite.createChange(true);
1877 				if (change != null)
1878 					manager.manage(entry.getKey(), change);
1879 			}
1880 		}
1881 	}
1882 
1883 	/**
1884 	 * Resets the environment before the first wizard page becomes visible.
1885 	 */
resetEnvironment()1886 	public void resetEnvironment() {
1887 		ICompilationUnit unit= getDeclaringType().getCompilationUnit();
1888 		if (fLayer)
1889 			unit= unit.findWorkingCopy(fOwner);
1890 		resetWorkingCopies(unit);
1891 	}
1892 
1893 	@Override
rewriteTypeOccurrences(final TextEditBasedChangeManager manager, final ASTRequestor requestor, final CompilationUnitRewrite rewrite, final ICompilationUnit unit, final CompilationUnit node, final Set<String> replacements, final IProgressMonitor monitor)1894 	protected 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 {
1895 		try {
1896 			monitor.beginTask("", 100); //$NON-NLS-1$
1897 			monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating);
1898 			CompilationUnitRewrite currentRewrite= null;
1899 			final CompilationUnitRewrite existingRewrite= fCompilationUnitRewrites.get(unit.getPrimary());
1900 			final boolean isTouched= existingRewrite != null;
1901 			if (isTouched)
1902 				currentRewrite= existingRewrite;
1903 			else
1904 				currentRewrite= new CompilationUnitRewrite(unit, node);
1905 			final Collection<ITypeConstraintVariable> collection= fTypeOccurrences.get(unit);
1906 			if (collection != null && !collection.isEmpty()) {
1907 				final IProgressMonitor subMonitor= new SubProgressMonitor(monitor, 100);
1908 				try {
1909 					subMonitor.beginTask("", collection.size() * 10); //$NON-NLS-1$
1910 					subMonitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating);
1911 					for (ITypeConstraintVariable iTypeConstraintVariable : collection) {
1912 						ISourceConstraintVariable variable= iTypeConstraintVariable;
1913 						if (variable instanceof ITypeConstraintVariable) {
1914 							ITypeConstraintVariable constraint= (ITypeConstraintVariable) variable;
1915 							TType estimate= (TType) constraint.getData(SuperTypeConstraintsSolver.DATA_TYPE_ESTIMATE);
1916 							if (estimate != null) {
1917 								final CompilationUnitRange range= constraint.getRange();
1918 								if (isTouched)
1919 									rewriteTypeOccurrence(range, estimate, requestor, currentRewrite, node, replacements, currentRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.SuperTypeRefactoringProcessor_update_type_occurrence, SET_SUPER_TYPE));
1920 								else {
1921 									final ASTNode result= NodeFinder.perform(node, range.getSourceRange());
1922 									if (result != null)
1923 										rewriteTypeOccurrence(estimate, currentRewrite, result, currentRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.SuperTypeRefactoringProcessor_update_type_occurrence, SET_SUPER_TYPE));
1924 								}
1925 								subMonitor.worked(10);
1926 							}
1927 						}
1928 					}
1929 				} finally {
1930 					subMonitor.done();
1931 				}
1932 			}
1933 			if (!isTouched) {
1934 				final TextChange change= currentRewrite.createChange(true);
1935 				if (change != null)
1936 					manager.manage(unit, change);
1937 			}
1938 		} finally {
1939 			monitor.done();
1940 		}
1941 	}
1942 
rewriteTypeOccurrences(final TextEditBasedChangeManager manager, final CompilationUnitRewrite sourceRewrite, final ICompilationUnit copy, final Set<String> replacements, final RefactoringStatus status, final IProgressMonitor monitor)1943 	protected void rewriteTypeOccurrences(final TextEditBasedChangeManager manager, final CompilationUnitRewrite sourceRewrite, final ICompilationUnit copy, final Set<String> replacements, final RefactoringStatus status, final IProgressMonitor monitor) {
1944 		try {
1945 			monitor.beginTask("", 100); //$NON-NLS-1$
1946 			monitor.setTaskName(RefactoringCoreMessages.PullUpRefactoring_checking);
1947 			final IType declaring= getDeclaringType();
1948 			final IJavaProject project= declaring.getJavaProject();
1949 			final ASTParser parser= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL);
1950 			parser.setWorkingCopyOwner(fOwner);
1951 			parser.setResolveBindings(true);
1952 			parser.setProject(project);
1953 			parser.setCompilerOptions(RefactoringASTParser.getCompilerOptions(project));
1954 			parser.createASTs(new ICompilationUnit[] { copy}, new String[0], new ASTRequestor() {
1955 
1956 				@Override
1957 				public final void acceptAST(final ICompilationUnit unit, final CompilationUnit node) {
1958 					try {
1959 						final IType subType= (IType) JavaModelUtil.findInCompilationUnit(unit, declaring);
1960 						final AbstractTypeDeclaration subDeclaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(subType, node);
1961 						if (subDeclaration != null) {
1962 							final ITypeBinding subBinding= subDeclaration.resolveBinding();
1963 							if (subBinding != null) {
1964 								ITypeBinding superBinding= null;
1965 								for (ITypeBinding superBinding2 : Bindings.getAllSuperTypes(subBinding)) {
1966 									String name= superBinding2.getName();
1967 									if (name.startsWith(fDestinationType.getElementName()))
1968 										superBinding= superBinding2;
1969 								}
1970 								if (superBinding != null) {
1971 									solveSuperTypeConstraints(unit, node, subType, subBinding, superBinding, new SubProgressMonitor(monitor, 80), status);
1972 									if (!status.hasFatalError())
1973 										rewriteTypeOccurrences(manager, this, sourceRewrite, unit, node, replacements, status, new SubProgressMonitor(monitor, 120));
1974 								}
1975 							}
1976 						}
1977 					} catch (JavaModelException exception) {
1978 						JavaPlugin.log(exception);
1979 						status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_internal_error));
1980 					}
1981 				}
1982 
1983 				@Override
1984 				public final void acceptBinding(final String key, final IBinding binding) {
1985 					// Do nothing
1986 				}
1987 			}, new NullProgressMonitor());
1988 		} finally {
1989 			monitor.done();
1990 		}
1991 	}
1992 
1993 	/**
1994 	 * Sets the methods to declare abstract.
1995 	 *
1996 	 * @param methods
1997 	 *            the methods to declare abstract
1998 	 */
setAbstractMethods(final IMethod[] methods)1999 	public void setAbstractMethods(final IMethod[] methods) {
2000 		Assert.isNotNull(methods);
2001 		fAbstractMethods= methods;
2002 	}
2003 
2004 	/**
2005 	 * Determines whether to create method stubs for non-implemented abstract
2006 	 * methods.
2007 	 *
2008 	 * @param create
2009 	 *            <code>true</code> to create stubs, <code>false</code>
2010 	 *            otherwise
2011 	 */
setCreateMethodStubs(final boolean create)2012 	public void setCreateMethodStubs(final boolean create) {
2013 		fCreateMethodStubs= create;
2014 	}
2015 
2016 	/**
2017 	 * Sets the methods to delete
2018 	 *
2019 	 * @param methods
2020 	 *            the methods to delete
2021 	 */
setDeletedMethods(final IMethod[] methods)2022 	public void setDeletedMethods(final IMethod[] methods) {
2023 		Assert.isNotNull(methods);
2024 		fDeletedMethods= methods;
2025 	}
2026 
2027 	/**
2028 	 * Sets the destination type.
2029 	 *
2030 	 * @param type
2031 	 *            the destination type
2032 	 */
setDestinationType(final IType type)2033 	public void setDestinationType(final IType type) {
2034 		Assert.isNotNull(type);
2035 		if (!type.equals(fDestinationType))
2036 			fCachedDestinationTypeHierarchy= null;
2037 		fDestinationType= type;
2038 	}
2039 
2040 	/**
2041 	 * Sets the members to move.
2042 	 *
2043 	 * @param members
2044 	 *            the members to move
2045 	 */
setMembersToMove(final IMember[] members)2046 	public void setMembersToMove(final IMember[] members) {
2047 		Assert.isNotNull(members);
2048 		fMembersToMove= (IMember[]) SourceReferenceUtil.sortByOffset(members);
2049 	}
2050 }
2051