KickJava   Java API By Example, From Geeks To Geeks.

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


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

11 package org.eclipse.jdt.internal.corext.refactoring.structure;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Arrays JavaDoc;
15 import java.util.Collections JavaDoc;
16 import java.util.Comparator JavaDoc;
17 import java.util.HashMap JavaDoc;
18 import java.util.HashSet JavaDoc;
19 import java.util.Iterator JavaDoc;
20 import java.util.List JavaDoc;
21 import java.util.Map JavaDoc;
22 import java.util.Set JavaDoc;
23
24 import org.eclipse.text.edits.TextEdit;
25 import org.eclipse.text.edits.TextEditGroup;
26
27 import org.eclipse.core.runtime.Assert;
28 import org.eclipse.core.runtime.CoreException;
29 import org.eclipse.core.runtime.IProgressMonitor;
30 import org.eclipse.core.runtime.NullProgressMonitor;
31 import org.eclipse.core.runtime.SubProgressMonitor;
32
33 import org.eclipse.core.resources.IFile;
34 import org.eclipse.core.resources.IResource;
35
36 import org.eclipse.jface.text.BadLocationException;
37 import org.eclipse.jface.text.Document;
38 import org.eclipse.jface.text.IDocument;
39
40 import org.eclipse.ltk.core.refactoring.Change;
41 import org.eclipse.ltk.core.refactoring.CompositeChange;
42 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
43 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
44 import org.eclipse.ltk.core.refactoring.RefactoringStatusContext;
45 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
46 import org.eclipse.ltk.core.refactoring.participants.MoveArguments;
47 import org.eclipse.ltk.core.refactoring.participants.MoveProcessor;
48 import org.eclipse.ltk.core.refactoring.participants.ParticipantManager;
49 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
50 import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant;
51 import org.eclipse.ltk.core.refactoring.participants.ResourceChangeChecker;
52 import org.eclipse.ltk.core.refactoring.participants.SharableParticipants;
53
54 import org.eclipse.jdt.core.Flags;
55 import org.eclipse.jdt.core.ICompilationUnit;
56 import org.eclipse.jdt.core.IField;
57 import org.eclipse.jdt.core.IInitializer;
58 import org.eclipse.jdt.core.IJavaElement;
59 import org.eclipse.jdt.core.IJavaProject;
60 import org.eclipse.jdt.core.IMember;
61 import org.eclipse.jdt.core.IMethod;
62 import org.eclipse.jdt.core.ISourceRange;
63 import org.eclipse.jdt.core.IType;
64 import org.eclipse.jdt.core.JavaModelException;
65 import org.eclipse.jdt.core.dom.ASTNode;
66 import org.eclipse.jdt.core.dom.ASTVisitor;
67 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
68 import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
69 import org.eclipse.jdt.core.dom.BodyDeclaration;
70 import org.eclipse.jdt.core.dom.EnumDeclaration;
71 import org.eclipse.jdt.core.dom.FieldDeclaration;
72 import org.eclipse.jdt.core.dom.IBinding;
73 import org.eclipse.jdt.core.dom.IMethodBinding;
74 import org.eclipse.jdt.core.dom.ITypeBinding;
75 import org.eclipse.jdt.core.dom.IVariableBinding;
76 import org.eclipse.jdt.core.dom.MethodDeclaration;
77 import org.eclipse.jdt.core.dom.Modifier;
78 import org.eclipse.jdt.core.dom.SimpleName;
79 import org.eclipse.jdt.core.dom.TypeDeclaration;
80 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
81 import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
82 import org.eclipse.jdt.core.dom.rewrite.ITrackedNodePosition;
83 import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
84 import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
85 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
86 import org.eclipse.jdt.core.refactoring.descriptors.MoveStaticMembersDescriptor;
87 import org.eclipse.jdt.core.search.IJavaSearchConstants;
88 import org.eclipse.jdt.core.search.SearchMatch;
89 import org.eclipse.jdt.core.search.SearchPattern;
90
91 import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings;
92 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
93 import org.eclipse.jdt.internal.corext.dom.ModifierRewrite;
94 import org.eclipse.jdt.internal.corext.dom.NodeFinder;
95 import org.eclipse.jdt.internal.corext.refactoring.Checks;
96 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor;
97 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
98 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
99 import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
100 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
101 import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory;
102 import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine2;
103 import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
104 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
105 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
106 import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring;
107 import org.eclipse.jdt.internal.corext.refactoring.delegates.DelegateFieldCreator;
108 import org.eclipse.jdt.internal.corext.refactoring.delegates.DelegateMethodCreator;
109 import org.eclipse.jdt.internal.corext.refactoring.participants.JavaProcessors;
110 import org.eclipse.jdt.internal.corext.refactoring.structure.MemberVisibilityAdjustor.IncomingMemberVisibilityAdjustment;
111 import org.eclipse.jdt.internal.corext.refactoring.tagging.ICommentProvider;
112 import org.eclipse.jdt.internal.corext.refactoring.tagging.IDelegateUpdating;
113 import org.eclipse.jdt.internal.corext.refactoring.tagging.IScriptableRefactoring;
114 import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil;
115 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
116 import org.eclipse.jdt.internal.corext.util.JdtFlags;
117 import org.eclipse.jdt.internal.corext.util.Messages;
118 import org.eclipse.jdt.internal.corext.util.SearchUtils;
119 import org.eclipse.jdt.internal.corext.util.Strings;
120
121 import org.eclipse.jdt.ui.JavaElementLabels;
122 import org.eclipse.jdt.ui.refactoring.IRefactoringProcessorIds;
123
124 import org.eclipse.jdt.internal.ui.JavaPlugin;
125 import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings;
126
127 public final class MoveStaticMembersProcessor extends MoveProcessor implements IDelegateUpdating, IScriptableRefactoring, ICommentProvider {
128
129     private static final String JavaDoc ATTRIBUTE_DELEGATE="delegate"; //$NON-NLS-1$
130
private static final String JavaDoc ATTRIBUTE_DEPRECATE="deprecate"; //$NON-NLS-1$
131
private static final String JavaDoc TRACKED_POSITION_PROPERTY= "MoveStaticMembersProcessor.trackedPosition"; //$NON-NLS-1$
132

133     private IMember[] fMembersToMove;
134     private IType fDestinationType;
135     private String JavaDoc fDestinationTypeName;
136     
137     private CodeGenerationSettings fPreferences;
138     private CompositeChange fChange;
139     private CompilationUnitRewrite fSource;
140     private ITypeBinding fSourceBinding;
141     private CompilationUnitRewrite fTarget;
142     private IBinding[] fMemberBindings;
143     private BodyDeclaration[] fMemberDeclarations;
144     private boolean fDelegateUpdating;
145     private boolean fDelegateDeprecation;
146     private String JavaDoc fComment;
147
148     private static class TypeReferenceFinder extends ASTVisitor {
149         List JavaDoc fResult= new ArrayList JavaDoc();
150         Set JavaDoc fDefined= new HashSet JavaDoc();
151         public static List JavaDoc perform(ASTNode root) {
152             TypeReferenceFinder visitor= new TypeReferenceFinder();
153             root.accept(visitor);
154             return visitor.fResult;
155         }
156         public boolean visit(TypeDeclaration node) {
157             fDefined.add(node.resolveBinding());
158             return true;
159         }
160         public boolean visit(SimpleName node) {
161             IBinding binding= node.resolveBinding();
162             if (!(binding instanceof ITypeBinding))
163                 return true;
164             if (!fDefined.contains(binding))
165                 fResult.add(binding);
166             return true;
167         }
168
169         public boolean visit(AnnotationTypeDeclaration node) {
170             fDefined.add(node.resolveBinding());
171             return true;
172         }
173
174         public boolean visit(EnumDeclaration node) {
175             fDefined.add(node.resolveBinding());
176             return true;
177         }
178     }
179
180     /**
181      * Creates a new move static members processor.
182      * @param members the members to move, or <code>null</code> if invoked by scripting
183      * @param settings the code generation settings, or <code>null</code> if invoked by scripting
184      */

185     public MoveStaticMembersProcessor(IMember[] members, CodeGenerationSettings settings) {
186         fMembersToMove= members;
187         fPreferences= settings;
188         fDelegateUpdating= false;
189         fDelegateDeprecation= true;
190     }
191     
192     /**
193      * {@inheritDoc}
194      */

195     public boolean isApplicable() throws CoreException {
196         return RefactoringAvailabilityTester.isMoveStaticMembersAvailable(fMembersToMove);
197     }
198
199     /**
200      * {@inheritDoc}
201      */

202     public Object JavaDoc[] getElements() {
203         Object JavaDoc[] result= new Object JavaDoc[fMembersToMove.length];
204         System.arraycopy(fMembersToMove, 0, result, 0, fMembersToMove.length);
205         return result;
206     }
207
208     /**
209      * {@inheritDoc}
210      */

211     public String JavaDoc getIdentifier() {
212         return IRefactoringProcessorIds.MOVE_STATIC_MEMBERS_PROCESSOR;
213     }
214
215     /**
216      * {@inheritDoc}
217      */

218     public RefactoringParticipant[] loadParticipants(RefactoringStatus status, SharableParticipants sharedParticipants) throws CoreException {
219         List JavaDoc result= new ArrayList JavaDoc();
220         MoveArguments args= new MoveArguments(fDestinationType, true);
221         String JavaDoc[] natures= JavaProcessors.computeAffectedNaturs(fMembersToMove);
222         for (int i= 0; i < fMembersToMove.length; i++) {
223             IMember member= fMembersToMove[i];
224             result.addAll(Arrays.asList(ParticipantManager.loadMoveParticipants(
225                 status, this, member, args, natures, sharedParticipants)));
226         }
227         return (RefactoringParticipant[])result.toArray(new RefactoringParticipant[result.size()]);
228     }
229     
230     //------------------- IDelegateUpdating ----------------------
231

232     public boolean canEnableDelegateUpdating() {
233         try {
234             for (int i= 0; i < fMembersToMove.length; i++) {
235                 if (isDelegateCreationAvailable(fMembersToMove[i]))
236                     return true;
237             }
238         } catch (JavaModelException e) {
239             return false;
240         }
241         return false;
242     }
243
244     private boolean isDelegateCreationAvailable(IMember member) throws JavaModelException {
245         if (member instanceof IMethod)
246             return true;
247         if (member instanceof IField && RefactoringAvailabilityTester.isDelegateCreationAvailable(((IField)member)))
248             return true;
249         return false;
250     }
251     
252     public boolean getDelegateUpdating() {
253         return fDelegateUpdating;
254     }
255
256     public void setDelegateUpdating(boolean updating) {
257         fDelegateUpdating= updating;
258     }
259
260     public boolean getDeprecateDelegates() {
261         return fDelegateDeprecation;
262     }
263
264     public void setDeprecateDelegates(boolean deprecate) {
265         fDelegateDeprecation= deprecate;
266     }
267
268     public String JavaDoc getProcessorName() {
269         return RefactoringCoreMessages.MoveMembersRefactoring_Move_Members;
270     }
271
272     public IType getDestinationType() {
273         return fDestinationType;
274     }
275
276     public void setDestinationTypeFullyQualifiedName(String JavaDoc fullyQualifiedTypeName) throws JavaModelException {
277         Assert.isNotNull(fullyQualifiedTypeName);
278         fDestinationType= resolveType(fullyQualifiedTypeName);
279         //workaround for bug 36032: IJavaProject#findType(..) doesn't find secondary type
280
fDestinationTypeName= fullyQualifiedTypeName;
281     }
282     
283     public IMember[] getMembersToMove() {
284         return fMembersToMove;
285     }
286     
287     public IType getDeclaringType() {
288         //all methods declared in same type - checked in precondition
289
return fMembersToMove[0].getDeclaringType(); //index safe - checked in areAllMoveable()
290
}
291     
292     private IType resolveType(String JavaDoc qualifiedTypeName) throws JavaModelException{
293         IType type= getDeclaringType().getJavaProject().findType(qualifiedTypeName);
294         if (type == null)
295             type= getDeclaringType().getJavaProject().findType(getDeclaringType().getPackageFragment().getElementName(), qualifiedTypeName);
296         return type;
297     }
298     
299     //---- Activation checking ------------------------------------
300

301     public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
302         try {
303             pm.beginTask(RefactoringCoreMessages.MoveMembersRefactoring_checking, 1);
304             RefactoringStatus result= new RefactoringStatus();
305             result.merge(checkDeclaringType());
306             pm.worked(1);
307             if (result.hasFatalError())
308                 return result;
309             
310             fSource= new CompilationUnitRewrite(fMembersToMove[0].getCompilationUnit());
311             fSourceBinding= (ITypeBinding)((SimpleName)NodeFinder.perform(fSource.getRoot(), fMembersToMove[0].getDeclaringType().getNameRange())).resolveBinding();
312             fMemberBindings= getMemberBindings();
313             if (fSourceBinding == null || hasUnresolvedMemberBinding()) {
314                 result.addFatalError(Messages.format(
315                     RefactoringCoreMessages.MoveMembersRefactoring_compile_errors,
316                     fSource.getCu().getElementName()));
317             }
318             fMemberDeclarations= getASTMembers(result);
319             return result;
320         } finally {
321             pm.done();
322         }
323     }
324     
325     private boolean hasUnresolvedMemberBinding() {
326         for (int i= 0; i < fMemberBindings.length; i++) {
327             if (fMemberBindings[i] == null)
328                 return true;
329         }
330         return false;
331     }
332     
333     private RefactoringStatus checkDeclaringType(){
334         IType declaringType= getDeclaringType();
335                 
336         if (JavaModelUtil.getFullyQualifiedName(declaringType).equals("java.lang.Object")) //$NON-NLS-1$
337
return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveMembersRefactoring_Object);
338
339         if (declaringType.isBinary())
340             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveMembersRefactoring_binary);
341
342         if (declaringType.isReadOnly())
343             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveMembersRefactoring_read_only);
344         
345         return null;
346     }
347     
348     //---- Input checking ------------------------------------
349

350     public RefactoringStatus checkFinalConditions(IProgressMonitor pm, CheckConditionsContext context) throws CoreException {
351         fTarget= null;
352         try {
353             pm.beginTask(RefactoringCoreMessages.MoveMembersRefactoring_checking, 10);
354             
355             RefactoringStatus result= new RefactoringStatus();
356             
357             fSource.clearASTAndImportRewrites();
358             
359             result.merge(checkDestinationType());
360             if (result.hasFatalError())
361                 return result;
362                         
363             result.merge(checkDestinationInsideTypeToMove());
364             if (result.hasFatalError())
365                 return result;
366
367             result.merge(MemberCheckUtil.checkMembersInDestinationType(fMembersToMove, fDestinationType));
368             if (result.hasFatalError())
369                 return result;
370             
371             result.merge(checkNativeMovedMethods(new SubProgressMonitor(pm, 1)));
372             
373             if (result.hasFatalError())
374                 return result;
375             
376             List JavaDoc modifiedCus= new ArrayList JavaDoc();
377             createChange(modifiedCus, result, new SubProgressMonitor(pm, 7));
378             IFile[] changedFiles= getAllFilesToModify(modifiedCus);
379             ResourceChangeChecker checker= (ResourceChangeChecker)context.getChecker(ResourceChangeChecker.class);
380             for (int i= 0; i < changedFiles.length; i++) {
381                 checker.getDeltaFactory().change(changedFiles[i]);
382             }
383             
384             return result;
385         } finally {
386             pm.done();
387         }
388     }
389     
390     private IFile[] getAllFilesToModify(List JavaDoc modifiedCus) {
391         Set JavaDoc result= new HashSet JavaDoc();
392         IResource resource= fDestinationType.getCompilationUnit().getResource();
393         result.add(resource);
394         for (int i= 0; i < fMembersToMove.length; i++) {
395             resource= fMembersToMove[i].getCompilationUnit().getResource();
396             if (resource != null)
397                 result.add(resource);
398         }
399         for (Iterator JavaDoc iter= modifiedCus.iterator(); iter.hasNext();) {
400             ICompilationUnit unit= (ICompilationUnit)iter.next();
401             if (unit.getResource() != null)
402                 result.add(unit.getResource());
403         }
404         return (IFile[]) result.toArray(new IFile[result.size()]);
405     }
406
407     private RefactoringStatus checkDestinationType() throws JavaModelException {
408         if (fDestinationType == null){
409             String JavaDoc message= Messages.format(RefactoringCoreMessages.MoveMembersRefactoring_not_found, fDestinationTypeName);
410             return RefactoringStatus.createFatalErrorStatus(message);
411         }
412         
413         if (fDestinationType.equals(getDeclaringType())){
414             String JavaDoc message= Messages.format(RefactoringCoreMessages.MoveMembersRefactoring_same,
415                 JavaElementUtil.createSignature(fDestinationType));
416             return RefactoringStatus.createFatalErrorStatus(message);
417         }
418         
419         if (! fDestinationType.exists()){
420             String JavaDoc message= Messages.format(RefactoringCoreMessages.MoveMembersRefactoring_not_exist,
421                 JavaElementUtil.createSignature(fDestinationType));
422             return RefactoringStatus.createFatalErrorStatus(message);
423         }
424             
425         if (fDestinationType.isBinary()){
426             String JavaDoc message= Messages.format(RefactoringCoreMessages.MoveMembersRefactoring_dest_binary,
427                 JavaElementUtil.createSignature(fDestinationType));
428             return RefactoringStatus.createFatalErrorStatus(message);
429         }
430
431         RefactoringStatus result= new RefactoringStatus();
432
433         if (fDestinationType.isInterface() && ! getDeclaringType().isInterface())
434             result.merge(checkFieldsForInterface());
435         if (result.hasFatalError())
436             return result;
437
438         // no checking required for moving interface fields to classes
439

440         if (! ((JdtFlags.isStatic(fDestinationType)) || (fDestinationType.getDeclaringType() == null))){
441             String JavaDoc message= RefactoringCoreMessages.MoveMembersRefactoring_static_declaration;
442             result.addError(message);
443         }
444                 
445         return result;
446     }
447     
448     private RefactoringStatus checkDestinationInsideTypeToMove() throws JavaModelException {
449         RefactoringStatus result= new RefactoringStatus();
450         for (int i= 0; i < fMembersToMove.length; i++) {
451             if (! (fMembersToMove[i] instanceof IType))
452                 continue;
453             IType type= (IType) fMembersToMove[i];
454             if (fDestinationType.equals(type) || JavaElementUtil.isAncestorOf(type, fDestinationType)) {
455                 String JavaDoc message= Messages.format(RefactoringCoreMessages.MoveMembersRefactoring_inside,
456                         new String JavaDoc[] {JavaModelUtil.getFullyQualifiedName(type),
457                                 JavaModelUtil.getFullyQualifiedName(fDestinationType)});
458                 RefactoringStatusContext context= JavaStatusContext.create(fDestinationType.getCompilationUnit(), fDestinationType.getNameRange());
459                 result.addFatalError(message, context);
460                 return result;
461             }
462         }
463         return result;
464     }
465
466     private RefactoringStatus checkFieldsForInterface() throws JavaModelException {
467         //could be more clever and make field final if it is only written once...
468
RefactoringStatus result= new RefactoringStatus();
469         for (int i= 0; i < fMembersToMove.length; i++) {
470             if (! canMoveToInterface(fMembersToMove[i])) {
471                 String JavaDoc message= RefactoringCoreMessages.MoveMembersRefactoring_only_public_static;
472                 result.addError(message, JavaStatusContext.create(fMembersToMove[i]));
473             }
474         }
475         return result;
476     }
477
478     private boolean canMoveToInterface(IMember member) throws JavaModelException {
479         int flags= member.getFlags();
480         switch (member.getElementType()) {
481             case IJavaElement.FIELD:
482                 if (!(Flags.isPublic(flags) && Flags.isStatic(flags) && Flags.isFinal(flags)))
483                     return false;
484                 if (Flags.isEnum(flags))
485                     return false;
486                 VariableDeclarationFragment declaration= ASTNodeSearchUtil.getFieldDeclarationFragmentNode((IField) member, fSource.getRoot());
487                 if (declaration != null)
488                     return declaration.getInitializer() != null;
489
490             case IJavaElement.TYPE: {
491                 IType type= (IType) member;
492                 if (type.isInterface() && !Checks.isTopLevel(type))
493                     return true;
494                 return (Flags.isPublic(flags) && Flags.isStatic(flags));
495             }
496             default:
497                 return false;
498         }
499     }
500
501     private RefactoringStatus checkMovedMemberAvailability(IMember memberToMove, IProgressMonitor pm) throws JavaModelException{
502         RefactoringStatus result= new RefactoringStatus();
503         if (memberToMove instanceof IType) { // recursively check accessibility of member type's members
504
IJavaElement[] typeMembers= ((IType) memberToMove).getChildren();
505             pm.beginTask(RefactoringCoreMessages.MoveMembersRefactoring_checking, typeMembers.length + 1);
506             for (int i= 0; i < typeMembers.length; i++) {
507                 if (typeMembers[i] instanceof IInitializer)
508                     pm.worked(1);
509                 else
510                     result.merge(checkMovedMemberAvailability((IMember) typeMembers[i], new SubProgressMonitor(pm, 1)));
511             }
512         } else {
513             pm.beginTask(RefactoringCoreMessages.MoveMembersRefactoring_checking, 1);
514         }
515
516         IType[] blindAccessorTypes= getTypesNotSeeingMovedMember(memberToMove, new SubProgressMonitor(pm, 1), result);
517         for (int k= 0; k < blindAccessorTypes.length; k++) {
518             String JavaDoc message= createNonAccessibleMemberMessage(memberToMove, blindAccessorTypes[k],/*moved*/true);
519             result.addError(message, JavaStatusContext.create(memberToMove));
520         }
521         pm.done();
522         return result;
523     }
524     
525     private IType[] getTypesNotSeeingMovedMember(IMember member, IProgressMonitor pm, RefactoringStatus status) throws JavaModelException {
526         if (JdtFlags.isPublic(member) && JdtFlags.isPublic(fDestinationType))
527             return new IType[0];
528
529         HashSet JavaDoc blindAccessorTypes= new HashSet JavaDoc(); // referencing, but access to destination type illegal
530
SearchResultGroup[] references= getReferences(member, new SubProgressMonitor(pm, 1), status);
531         for (int i = 0; i < references.length; i++) {
532             SearchMatch[] searchResults= references[i].getSearchResults();
533             for (int k= 0; k < searchResults.length; k++) {
534                 SearchMatch searchResult= searchResults[k];
535                 IJavaElement element= SearchUtils.getEnclosingJavaElement(searchResult);
536                 IType type= (IType) element.getAncestor(IJavaElement.TYPE);
537                 if (type != null //reference can e.g. be an import declaration
538
&& ! blindAccessorTypes.contains(type)
539                         && ! isWithinMemberToMove(searchResult)
540                         && ! isVisibleFrom(member, getDestinationType(), type)) {
541                     blindAccessorTypes.add(type);
542                 }
543             }
544         }
545         
546         if (fDelegateUpdating && isDelegateCreationAvailable(member)) {
547             // ensure moved member is visible from the delegate
548
IType type= member.getDeclaringType();
549             if (!blindAccessorTypes.contains(type) && !isVisibleFrom(member, getDestinationType(), type))
550                 blindAccessorTypes.add(type);
551         }
552         
553         return (IType[]) blindAccessorTypes.toArray(new IType[blindAccessorTypes.size()]);
554     }
555
556     private String JavaDoc createNonAccessibleMemberMessage(IMember member, IType accessingType, boolean moved){
557         //Non-visibility can have various reasons and always displaying all visibility
558
//flags for all enclosing elements would be too heavy. Context reveals exact cause.
559
IType declaringType= moved ? getDestinationType() : getDeclaringType();
560         String JavaDoc message;
561         switch (member.getElementType()){
562             case IJavaElement.FIELD: {
563                 if (moved)
564                     message= Messages.format(RefactoringCoreMessages.MoveMembersRefactoring_moved_field,
565                                 new String JavaDoc[]{JavaElementUtil.createFieldSignature((IField)member),
566                                     JavaModelUtil.getFullyQualifiedName(accessingType),
567                                     JavaModelUtil.getFullyQualifiedName(declaringType)});
568                 else
569                     message= Messages.format(RefactoringCoreMessages.MoveMembersRefactoring_accessed_field,
570                                 new String JavaDoc[]{JavaElementUtil.createFieldSignature((IField)member),
571                                     JavaModelUtil.getFullyQualifiedName(accessingType)});
572                 return message;
573             }
574             case IJavaElement.METHOD: {
575                 if (moved)
576                     message= Messages.format(RefactoringCoreMessages.MoveMembersRefactoring_moved_method,
577                                 new String JavaDoc[]{JavaElementUtil.createMethodSignature((IMethod)member),
578                                     JavaModelUtil.getFullyQualifiedName(accessingType),
579                                     JavaModelUtil.getFullyQualifiedName(declaringType)});
580                 else
581                     message= Messages.format(RefactoringCoreMessages.MoveMembersRefactoring_accessed_method,
582                                 new String JavaDoc[]{JavaElementUtil.createMethodSignature((IMethod)member),
583                                     JavaModelUtil.getFullyQualifiedName(accessingType)});
584                                  
585                 return message;
586             }
587             case IJavaElement.TYPE:{
588                 if (moved)
589                     message= Messages.format(RefactoringCoreMessages.MoveMembersRefactoring_moved_type,
590                                 new String JavaDoc[]{JavaModelUtil.getFullyQualifiedName(((IType)member)),
591                                     JavaModelUtil.getFullyQualifiedName(accessingType),
592                                     JavaModelUtil.getFullyQualifiedName(declaringType)});
593                 else
594                     message= Messages.format(RefactoringCoreMessages.MoveMembersRefactoring_accessed_type,
595                                 new String JavaDoc[]{JavaModelUtil.getFullyQualifiedName(((IType)member)),
596                                     JavaModelUtil.getFullyQualifiedName(accessingType)});
597                 return message;
598             }
599             default:
600                 Assert.isTrue(false);
601                 return null;
602         }
603     }
604
605     private static SearchResultGroup[] getReferences(IMember member, IProgressMonitor monitor, RefactoringStatus status) throws JavaModelException {
606         final RefactoringSearchEngine2 engine= new RefactoringSearchEngine2(SearchPattern.createPattern(member, IJavaSearchConstants.REFERENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE));
607         engine.setFiltering(true, true);
608         engine.setScope(RefactoringScopeFactory.create(member));
609         engine.setStatus(status);
610         engine.searchPattern(new SubProgressMonitor(monitor, 1));
611         return (SearchResultGroup[]) engine.getResults();
612     }
613
614     private static boolean isVisibleFrom(IMember member, IType newMemberDeclaringType, IType accessingType) throws JavaModelException{
615         int memberVisibility= JdtFlags.getVisibilityCode(newMemberDeclaringType);
616             
617         IType declaringType= newMemberDeclaringType.getDeclaringType();
618         while (declaringType != null) { //get lowest visibility in all parent types of newMemberDeclaringType
619
memberVisibility= JdtFlags.getLowerVisibility(
620                     memberVisibility, JdtFlags.getVisibilityCode(declaringType));
621             declaringType= declaringType.getDeclaringType();
622         }
623         
624         switch (memberVisibility) {
625             case Modifier.PRIVATE :
626                 return isEqualOrEnclosedType(accessingType, newMemberDeclaringType);
627                 
628             case Modifier.NONE :
629                 return JavaModelUtil.isSamePackage(accessingType.getPackageFragment(), newMemberDeclaringType.getPackageFragment());
630                     
631             case Modifier.PROTECTED :
632                 return JavaModelUtil.isSamePackage(accessingType.getPackageFragment(), newMemberDeclaringType.getPackageFragment())
633                         || accessingType.newSupertypeHierarchy(null).contains(newMemberDeclaringType);
634             
635             case Modifier.PUBLIC :
636                 return true;
637
638             default:
639                 Assert.isTrue(false);
640                 return false;
641         }
642     }
643     
644     private static boolean isEqualOrEnclosedType(IType inner, IType outer) {
645         while (inner != null) {
646             if (inner.equals(outer))
647                 return true;
648             else
649                 inner= inner.getDeclaringType();
650         }
651         return false;
652     }
653
654     private boolean isWithinMemberToMove(SearchMatch result) throws JavaModelException {
655         ICompilationUnit referenceCU= SearchUtils.getCompilationUnit(result);
656         if (! referenceCU.equals(fSource.getCu()))
657             return false;
658         int referenceStart= result.getOffset();
659         for (int i= 0; i < fMembersToMove.length; i++) {
660             ISourceRange range= fMembersToMove[i].getSourceRange();
661             if (range.getOffset() <= referenceStart && range.getOffset() + range.getLength() >= referenceStart)
662                 return true;
663         }
664         return false;
665     }
666
667     private RefactoringStatus checkNativeMovedMethods(IProgressMonitor pm) throws JavaModelException{
668         pm.beginTask(RefactoringCoreMessages.MoveMembersRefactoring_checking, fMembersToMove.length);
669         RefactoringStatus result= new RefactoringStatus();
670         for (int i= 0; i < fMembersToMove.length; i++) {
671             if (fMembersToMove[i].getElementType() != IJavaElement.METHOD)
672                 continue;
673             if (! JdtFlags.isNative(fMembersToMove[i]))
674                 continue;
675             String JavaDoc message= Messages.format(RefactoringCoreMessages.MoveMembersRefactoring_native,
676                 JavaElementUtil.createMethodSignature((IMethod)fMembersToMove[i]));
677             result.addWarning(message, JavaStatusContext.create(fMembersToMove[i]));
678             pm.worked(1);
679         }
680         pm.done();
681         return result;
682     }
683
684     public Change createChange(IProgressMonitor pm) throws CoreException {
685         pm.done();
686         return fChange;
687     }
688     
689     private void createChange(List JavaDoc modifiedCus, RefactoringStatus status, IProgressMonitor monitor) throws CoreException {
690         monitor.beginTask(RefactoringCoreMessages.MoveMembersRefactoring_creating, 5);
691         final IMember[] members= getMembersToMove();
692         String JavaDoc project= null;
693         final IJavaProject javaProject= getDeclaringType().getJavaProject();
694         if (javaProject != null)
695             project= javaProject.getElementName();
696         String JavaDoc header= null;
697         if (members.length == 1)
698             header= Messages.format(RefactoringCoreMessages.MoveStaticMembersProcessor_descriptor_description_single, new String JavaDoc[] { JavaElementLabels.getElementLabel(members[0], JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getElementLabel(fDestinationType, JavaElementLabels.ALL_FULLY_QUALIFIED) });
699         else
700             header= Messages.format(RefactoringCoreMessages.MoveStaticMembersProcessor_descriptor_description_multi, new String JavaDoc[] { String.valueOf(members.length), JavaElementLabels.getElementLabel(fDestinationType, JavaElementLabels.ALL_FULLY_QUALIFIED) });
701         int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE | RefactoringDescriptor.MULTI_CHANGE;
702         final IType declaring= members[0].getDeclaringType();
703         try {
704             if (declaring.isLocal() || declaring.isAnonymous())
705                 flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
706         } catch (JavaModelException exception) {
707             JavaPlugin.log(exception);
708         }
709         final String JavaDoc description= members.length == 1 ? Messages.format(RefactoringCoreMessages.MoveStaticMembersProcessor_description_descriptor_short_multi, members[0].getElementName()) : RefactoringCoreMessages.MoveMembersRefactoring_move_members;
710         final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header);
711         comment.addSetting(Messages.format(RefactoringCoreMessages.MoveStaticMembersProcessor_target_element_pattern, JavaElementLabels.getElementLabel(fDestinationType, JavaElementLabels.ALL_FULLY_QUALIFIED)));
712         final MoveStaticMembersDescriptor descriptor= new MoveStaticMembersDescriptor();
713         descriptor.setProject(project);
714         descriptor.setDescription(description);
715         descriptor.setComment(comment.asString());
716         descriptor.setFlags(flags);
717         descriptor.setDestinationType(fDestinationType);
718         descriptor.setKeepOriginal(fDelegateUpdating);
719         descriptor.setDeprecateDelegate(fDelegateDeprecation);
720         descriptor.setMembers(members);
721         fChange= new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.MoveMembersRefactoring_move_members);
722         fTarget= getCuRewrite(fDestinationType.getCompilationUnit());
723         ITypeBinding targetBinding= getDestinationBinding();
724         if (targetBinding == null) {
725             status.addFatalError(Messages.format(RefactoringCoreMessages.MoveMembersRefactoring_compile_errors, fTarget.getCu().getElementName()));
726             monitor.done();
727             return;
728         }
729
730         try {
731             Map JavaDoc adjustments= new HashMap JavaDoc();
732             IMember member= null;
733             SubProgressMonitor sub= new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL);
734             sub.beginTask(RefactoringCoreMessages.MoveMembersRefactoring_creating, fMembersToMove.length);
735             Set JavaDoc rewritten= new HashSet JavaDoc();
736             for (int index= 0; index < fMembersToMove.length; index++) {
737                 member= fMembersToMove[index];
738                 final MemberVisibilityAdjustor adjustor= new MemberVisibilityAdjustor(fDestinationType, member);
739                 adjustor.setAdjustments(adjustments);
740                 adjustor.setStatus(status);
741                 adjustor.setVisibilitySeverity(RefactoringStatus.WARNING);
742                 adjustor.setFailureSeverity(RefactoringStatus.WARNING);
743                 adjustor.setRewrite(fSource.getASTRewrite(), fSource.getRoot());
744                 adjustor.adjustVisibility(new NullProgressMonitor());
745
746                 if (fDelegateUpdating && isDelegateCreationAvailable(member)) {
747                     // Add a visibility adjustment so the moved member
748
// will be visible from within the delegate
749
ModifierKeyword threshold= adjustor.getVisibilityThreshold(member, fDestinationType, new NullProgressMonitor());
750                     IncomingMemberVisibilityAdjustment adjustment= (IncomingMemberVisibilityAdjustment) adjustments.get(member);
751                     ModifierKeyword kw= (adjustment != null) ? adjustment.getKeyword() : ModifierKeyword.fromFlagValue(JdtFlags.getVisibilityCode(member));
752                     if (MemberVisibilityAdjustor.hasLowerVisibility(kw, threshold)) {
753                         adjustments.put(member, new MemberVisibilityAdjustor.IncomingMemberVisibilityAdjustment(member, threshold, RefactoringStatus.createWarningStatus(Messages.format(MemberVisibilityAdjustor.getMessage(member), new String JavaDoc[] { MemberVisibilityAdjustor.getLabel(member), MemberVisibilityAdjustor.getLabel(threshold)}), JavaStatusContext.create(member))));
754                     }
755                 }
756
757                 // Check if destination type is visible from references ->
758
// error message if not (for example, when moving into a private type)
759
status.merge(checkMovedMemberAvailability(member, new SubProgressMonitor(sub, 1)));
760                 // Put rewrite info into code and into status
761
for (final Iterator JavaDoc iterator= rewritten.iterator(); iterator.hasNext();) {
762                     adjustments.remove(iterator.next());
763                 }
764                 rewritten.addAll(adjustments.keySet());
765                 adjustor.rewriteVisibility(new NullProgressMonitor());
766             }
767
768             // First update references in moved members, in order to extract the
769
// source.
770
String JavaDoc[] memberSources= getUpdatedMemberSource(status, fMemberDeclarations, targetBinding);
771             monitor.worked(1);
772             if (status.hasFatalError())
773                 return;
774
775             final RefactoringSearchEngine2 engine= new RefactoringSearchEngine2();
776             engine.setPattern(fMembersToMove, IJavaSearchConstants.ALL_OCCURRENCES);
777             engine.setGranularity(RefactoringSearchEngine2.GRANULARITY_COMPILATION_UNIT);
778             engine.setFiltering(true, true);
779             engine.setScope(RefactoringScopeFactory.create(fMembersToMove));
780             engine.setStatus(status);
781             engine.searchPattern(new NullProgressMonitor());
782             ICompilationUnit[] units= engine.getAffectedCompilationUnits();
783             modifiedCus.addAll(Arrays.asList(units));
784             final MemberVisibilityAdjustor adjustor= new MemberVisibilityAdjustor(fDestinationType, fDestinationType);
785             sub= new SubProgressMonitor(monitor, 1);
786             sub.beginTask(RefactoringCoreMessages.MoveMembersRefactoring_creating, units.length);
787             for (int index= 0; index < units.length; index++) {
788                 ICompilationUnit unit= units[index];
789                 CompilationUnitRewrite rewrite= getCuRewrite(unit);
790                 adjustor.setRewrites(Collections.singletonMap(unit, rewrite));
791                 adjustor.setAdjustments(adjustments);
792                 adjustor.rewriteVisibility(unit, new SubProgressMonitor(sub, 1));
793                 ReferenceAnalyzer analyzer= new ReferenceAnalyzer(rewrite, fMemberBindings, targetBinding, fSourceBinding);
794                 rewrite.getRoot().accept(analyzer);
795                 status.merge(analyzer.getStatus());
796                 if (status.hasFatalError()) {
797                     fChange= null;
798                     return;
799                 }
800                 if (!(fSource.getCu().equals(unit) || fTarget.getCu().equals(unit)))
801                     fChange.add(rewrite.createChange());
802             }
803             status.merge(moveMembers(fMemberDeclarations, memberSources));
804             fChange.add(fSource.createChange());
805             modifiedCus.add(fSource.getCu());
806             if (!fSource.getCu().equals(fTarget.getCu())) {
807                 fChange.add(fTarget.createChange());
808                 modifiedCus.add(fTarget.getCu());
809             }
810             monitor.worked(1);
811         } catch (BadLocationException exception) {
812             JavaPlugin.log(exception);
813         }
814     }
815     
816     private CompilationUnitRewrite getCuRewrite(ICompilationUnit unit) {
817         if (fSource.getCu().equals(unit))
818             return fSource;
819         if (fTarget != null && fTarget.getCu().equals(unit))
820             return fTarget;
821         return new CompilationUnitRewrite(unit);
822     }
823     
824     private ITypeBinding getDestinationBinding() throws JavaModelException {
825         ASTNode node= NodeFinder.perform(fTarget.getRoot(), fDestinationType.getNameRange());
826         if (!(node instanceof SimpleName))
827             return null;
828         IBinding binding= ((SimpleName)node).resolveBinding();
829         if (!(binding instanceof ITypeBinding))
830             return null;
831         return (ITypeBinding)binding;
832     }
833     
834     private IBinding[] getMemberBindings() throws JavaModelException {
835         IBinding[] result= new IBinding[fMembersToMove.length];
836         for (int i= 0; i < fMembersToMove.length; i++) {
837             IMember member= fMembersToMove[i];
838             SimpleName name= (SimpleName)NodeFinder.perform(fSource.getRoot(), member.getNameRange());
839             result[i]= name.resolveBinding();
840         }
841         return result;
842     }
843     
844     private String JavaDoc[] getUpdatedMemberSource(RefactoringStatus status, BodyDeclaration[] members, ITypeBinding target) throws CoreException, BadLocationException {
845         List JavaDoc typeRefs= new ArrayList JavaDoc();
846         boolean targetNeedsSourceImport= false;
847         boolean isSourceNotTarget= fSource != fTarget;
848         Set JavaDoc exclude= new HashSet JavaDoc();
849         for (int i= 0; i < members.length; i++) {
850             BodyDeclaration declaration= members[i];
851             if (declaration instanceof AbstractTypeDeclaration) {
852                 AbstractTypeDeclaration type= (AbstractTypeDeclaration) declaration;
853                 ITypeBinding binding= type.resolveBinding();
854                 if (binding != null)
855                     exclude.add(binding);
856             } else if (declaration instanceof MethodDeclaration) {
857                 MethodDeclaration method= (MethodDeclaration) declaration;
858                 IMethodBinding binding= method.resolveBinding();
859                 if (binding != null)
860                     exclude.add(binding);
861             } else if (declaration instanceof FieldDeclaration) {
862                 FieldDeclaration field= (FieldDeclaration) declaration;
863                 for (final Iterator JavaDoc iterator= field.fragments().iterator(); iterator.hasNext();) {
864                     VariableDeclarationFragment fragment= (VariableDeclarationFragment) iterator.next();
865                     IVariableBinding binding= fragment.resolveBinding();
866                     if (binding != null)
867                         exclude.add(binding);
868                 }
869             }
870         }
871         for (int i= 0; i < members.length; i++) {
872             BodyDeclaration declaration= members[i];
873             if (isSourceNotTarget)
874                 typeRefs.addAll(TypeReferenceFinder.perform(declaration));
875             MovedMemberAnalyzer analyzer= new MovedMemberAnalyzer(fSource, fMemberBindings, fSourceBinding, target);
876             declaration.accept(analyzer);
877             ImportRewriteUtil.addImports(fTarget, declaration, new HashMap JavaDoc(), new HashMap JavaDoc(), exclude, false);
878             if (getDeclaringType().isInterface() && !fDestinationType.isInterface()) {
879                 if (declaration instanceof FieldDeclaration) {
880                     FieldDeclaration fieldDecl= (FieldDeclaration) declaration;
881                     int psfModifiers= Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL;
882                     if ((fieldDecl.getModifiers() & psfModifiers) != psfModifiers) {
883                         ModifierRewrite.create(fSource.getASTRewrite(), fieldDecl).setModifiers(psfModifiers, null);
884                     }
885                 } else if (declaration instanceof AbstractTypeDeclaration) {
886                     AbstractTypeDeclaration typeDecl= (AbstractTypeDeclaration) declaration;
887                     int psModifiers= Modifier.PUBLIC | Modifier.STATIC;
888                     if ((typeDecl.getModifiers() & psModifiers) != psModifiers) {
889                         ModifierRewrite.create(fSource.getASTRewrite(), typeDecl).setModifiers(typeDecl.getModifiers() | psModifiers, null);
890                     }
891                 }
892             }
893             ITrackedNodePosition trackedPosition= fSource.getASTRewrite().track(declaration);
894             declaration.setProperty(TRACKED_POSITION_PROPERTY, trackedPosition);
895             targetNeedsSourceImport|= analyzer.targetNeedsSourceImport();
896             status.merge(analyzer.getStatus());
897         }
898         // Adjust imports
899
if (targetNeedsSourceImport && isSourceNotTarget) {
900             fTarget.getImportRewrite().addImport(fSourceBinding);
901         }
902         if (isSourceNotTarget) {
903             for (Iterator JavaDoc iter= typeRefs.iterator(); iter.hasNext();) {
904                 ITypeBinding binding= (ITypeBinding) iter.next();
905                 fTarget.getImportRewrite().addImport(binding);
906             }
907         }
908         // extract updated members
909
String JavaDoc[] updatedMemberSources= new String JavaDoc[members.length];
910         IDocument document= new Document(fSource.getCu().getBuffer().getContents());
911         TextEdit edit= fSource.getASTRewrite().rewriteAST(document, fSource.getCu().getJavaProject().getOptions(true));
912         edit.apply(document, TextEdit.UPDATE_REGIONS);
913         for (int i= 0; i < members.length; i++) {
914             updatedMemberSources[i]= getUpdatedMember(document, members[i]);
915         }
916         fSource.clearASTRewrite();
917         return updatedMemberSources;
918     }
919
920     private String JavaDoc getUpdatedMember(IDocument document, BodyDeclaration declaration) throws BadLocationException {
921         ITrackedNodePosition trackedPosition= (ITrackedNodePosition) declaration.getProperty(TRACKED_POSITION_PROPERTY);
922         return Strings.trimIndentation(document.get(trackedPosition.getStartPosition(), trackedPosition.getLength()), fPreferences.tabWidth, fPreferences.indentWidth, false);
923     }
924
925     private RefactoringStatus moveMembers(BodyDeclaration[] members, String JavaDoc[] sources) throws CoreException {
926         RefactoringStatus result= new RefactoringStatus();
927         AbstractTypeDeclaration destination= (AbstractTypeDeclaration)
928         ASTNodes.getParent(
929             NodeFinder.perform(fTarget.getRoot(), fDestinationType.getNameRange()),
930             AbstractTypeDeclaration.class);
931         ListRewrite containerRewrite= fTarget.getASTRewrite().getListRewrite(destination, destination.getBodyDeclarationsProperty());
932         
933         TextEditGroup delete= fSource.createGroupDescription(RefactoringCoreMessages.MoveMembersRefactoring_deleteMembers);
934         TextEditGroup add= fTarget.createGroupDescription(RefactoringCoreMessages.MoveMembersRefactoring_addMembers);
935         for (int i= 0; i < members.length; i++) {
936             BodyDeclaration declaration= members[i];
937             ASTNode removeImportsOf= null;
938             boolean addedDelegate= false;
939             
940             if (fDelegateUpdating) {
941                 if (declaration instanceof MethodDeclaration) {
942
943                     DelegateMethodCreator creator= new DelegateMethodCreator();
944                     creator.setDeclaration(declaration);
945                     creator.setDeclareDeprecated(fDelegateDeprecation);
946                     creator.setSourceRewrite(fSource);
947                     creator.setCopy(false);
948                     creator.setNewLocation(getDestinationBinding());
949                     creator.prepareDelegate();
950                     creator.createEdit();
951
952                     removeImportsOf= ((MethodDeclaration) declaration).getBody();
953                     addedDelegate= true;
954                 }
955                 if (declaration instanceof FieldDeclaration) {
956
957                     // Note: this FieldDeclaration only has one fragment (@see #getASTMembers(RefactoringStatus))
958
final VariableDeclarationFragment frag= (VariableDeclarationFragment) ((FieldDeclaration) declaration).fragments().get(0);
959                     
960                     if (!Modifier.isFinal(declaration.getModifiers())) {
961                         // Don't create a delegate for non-final fields
962
result.addInfo(Messages.format(RefactoringCoreMessages.DelegateCreator_cannot_create_field_delegate_not_final, frag.getName()), null);
963                     } else if (frag.getInitializer() == null) {
964                         // Don't create a delegate without an initializer.
965
result.addInfo(Messages.format(RefactoringCoreMessages.DelegateCreator_cannot_create_field_delegate_no_initializer, frag.getName()), null);
966                     } else {
967                         DelegateFieldCreator creator= new DelegateFieldCreator();
968                         creator.setDeclaration(declaration);
969                         creator.setDeclareDeprecated(fDelegateDeprecation);
970                         creator.setSourceRewrite(fSource);
971                         creator.setCopy(false);
972                         creator.setNewLocation(getDestinationBinding());
973                         creator.prepareDelegate();
974                         creator.createEdit();
975
976                         removeImportsOf= frag.getInitializer();
977                         addedDelegate= true;
978                     }
979                 }
980                 if (declaration instanceof AbstractTypeDeclaration) {
981                     result.addInfo(Messages.format(RefactoringCoreMessages.DelegateCreator_cannot_create_delegate_for_type, ((AbstractTypeDeclaration) declaration).getName().getIdentifier()),
982                             null);
983                 }
984             }
985             
986             if (!addedDelegate) {
987                 fSource.getASTRewrite().remove(declaration, delete);
988                 removeImportsOf= declaration;
989             }
990
991             if (removeImportsOf != null && fSource != fTarget)
992                 fSource.getImportRemover().registerRemovedNode(removeImportsOf);
993             
994             ASTNode node= fTarget.getASTRewrite().createStringPlaceholder(sources[i], declaration.getNodeType());
995             List JavaDoc container= containerRewrite.getRewrittenList();
996             int insertionIndex= ASTNodes.getInsertionIndex((BodyDeclaration) node, container);
997             containerRewrite.insertAt(node, insertionIndex, add);
998         }
999         return result;
1000    }
1001    
1002    private BodyDeclaration[] getASTMembers(RefactoringStatus status) throws JavaModelException {
1003        BodyDeclaration[] result= new BodyDeclaration[fMembersToMove.length];
1004        for (int i= 0; i < fMembersToMove.length; i++) {
1005            IMember member= fMembersToMove[i];
1006            ASTNode node= NodeFinder.perform(fSource.getRoot(), member.getNameRange());
1007            result[i]= (BodyDeclaration)ASTNodes.getParent(node, BodyDeclaration.class);
1008
1009            //Fix for bug 42383: exclude multiple VariableDeclarationFragments ("int a=1, b=2")
1010
//ReferenceAnalyzer#visit(FieldDeclaration node) depends on fragments().size() != 1 !
1011
if (result[i] instanceof FieldDeclaration
1012                    && ((FieldDeclaration) result[i]).fragments().size() != 1) {
1013                status.addFatalError(RefactoringCoreMessages.MoveMembersRefactoring_multi_var_fields);
1014                return result;
1015            }
1016            
1017        }
1018    
1019        //Sorting members is important for field declarations referring to previous fields.
1020
Arrays.sort(result, new Comparator JavaDoc() {
1021            public int compare(Object JavaDoc o1, Object JavaDoc o2) {
1022                return ((BodyDeclaration) o1).getStartPosition()
1023                        - ((BodyDeclaration) o2).getStartPosition();
1024            }
1025        });
1026        return result;
1027    }
1028
1029    public RefactoringStatus initialize(final RefactoringArguments arguments) {
1030        if (arguments instanceof JavaRefactoringArguments) {
1031            final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments;
1032            String JavaDoc handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT);
1033            if (handle != null) {
1034                final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false);
1035                if (element == null || !element.exists() || element.getElementType() != IJavaElement.TYPE)
1036                    return ScriptableRefactoring.createInputFatalStatus(element, getRefactoring().getName(), IJavaRefactorings.MOVE_STATIC_MEMBERS);
1037                else {
1038                    fDestinationType= (IType) element;
1039                    fDestinationTypeName= fDestinationType.getFullyQualifiedName();
1040                }
1041            } else
1042                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT));
1043            final String JavaDoc delegate= extended.getAttribute(ATTRIBUTE_DELEGATE);
1044            if (delegate != null) {
1045                fDelegateUpdating= Boolean.valueOf(delegate).booleanValue();
1046            } else
1047                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_DELEGATE));
1048            final String JavaDoc deprecate= extended.getAttribute(ATTRIBUTE_DEPRECATE);
1049            if (deprecate != null) {
1050                fDelegateDeprecation= Boolean.valueOf(deprecate).booleanValue();
1051            } else
1052                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_DEPRECATE));
1053            int count= 1;
1054            final List JavaDoc elements= new ArrayList JavaDoc();
1055            String JavaDoc attribute= JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + count;
1056            final RefactoringStatus status= new RefactoringStatus();
1057            while ((handle= extended.getAttribute(attribute)) != null) {
1058                final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false);
1059                if (element == null || !element.exists())
1060                    status.merge(ScriptableRefactoring.createInputWarningStatus(element, getRefactoring().getName(), IJavaRefactorings.MOVE_STATIC_MEMBERS));
1061                else
1062                    elements.add(element);
1063                count++;
1064                attribute= JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + count;
1065            }
1066            fMembersToMove= (IMember[]) elements.toArray(new IMember[elements.size()]);
1067            if (elements.isEmpty())
1068                return ScriptableRefactoring.createInputFatalStatus(null, getRefactoring().getName(), IJavaRefactorings.MOVE_STATIC_MEMBERS);
1069            IJavaProject project= null;
1070            if (fMembersToMove.length > 0)
1071                project= fMembersToMove[0].getJavaProject();
1072            fPreferences= JavaPreferencesSettings.getCodeGenerationSettings(project);
1073            if (!status.isOK())
1074                return status;
1075        } else
1076            return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
1077        return new RefactoringStatus();
1078    }
1079
1080    public boolean canEnableComment() {
1081        return true;
1082    }
1083
1084    public String JavaDoc getComment() {
1085        return fComment;
1086    }
1087
1088    public void setComment(String JavaDoc comment) {
1089        fComment= comment;
1090    }
1091
1092    public String JavaDoc getDelegateUpdatingTitle(boolean plural) {
1093        if (plural)
1094            return RefactoringCoreMessages.DelegateMethodCreator_keep_original_moved_plural;
1095        else
1096            return RefactoringCoreMessages.DelegateMethodCreator_keep_original_moved_singular;
1097    }
1098}
1099
Popular Tags