KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > rename > RenameFieldProcessor


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

11 package org.eclipse.jdt.internal.corext.refactoring.rename;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Arrays JavaDoc;
15 import java.util.List JavaDoc;
16
17 import org.eclipse.text.edits.ReplaceEdit;
18 import org.eclipse.text.edits.TextEdit;
19
20 import org.eclipse.core.runtime.Assert;
21 import org.eclipse.core.runtime.CoreException;
22 import org.eclipse.core.runtime.IProgressMonitor;
23 import org.eclipse.core.runtime.NullProgressMonitor;
24 import org.eclipse.core.runtime.SubProgressMonitor;
25
26 import org.eclipse.core.resources.IFile;
27
28 import org.eclipse.ltk.core.refactoring.Change;
29 import org.eclipse.ltk.core.refactoring.GroupCategorySet;
30 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
31 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
32 import org.eclipse.ltk.core.refactoring.TextChange;
33 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
34 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
35 import org.eclipse.ltk.core.refactoring.participants.RenameArguments;
36
37 import org.eclipse.jdt.core.Flags;
38 import org.eclipse.jdt.core.ICompilationUnit;
39 import org.eclipse.jdt.core.IField;
40 import org.eclipse.jdt.core.IJavaElement;
41 import org.eclipse.jdt.core.IJavaProject;
42 import org.eclipse.jdt.core.IMethod;
43 import org.eclipse.jdt.core.ISourceRange;
44 import org.eclipse.jdt.core.IType;
45 import org.eclipse.jdt.core.ITypeHierarchy;
46 import org.eclipse.jdt.core.JavaModelException;
47 import org.eclipse.jdt.core.WorkingCopyOwner;
48 import org.eclipse.jdt.core.dom.FieldDeclaration;
49 import org.eclipse.jdt.core.dom.MethodDeclaration;
50 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
51 import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
52 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
53 import org.eclipse.jdt.core.refactoring.descriptors.RenameJavaElementDescriptor;
54 import org.eclipse.jdt.core.search.IJavaSearchConstants;
55 import org.eclipse.jdt.core.search.IJavaSearchScope;
56 import org.eclipse.jdt.core.search.SearchEngine;
57 import org.eclipse.jdt.core.search.SearchMatch;
58 import org.eclipse.jdt.core.search.SearchPattern;
59
60 import org.eclipse.jdt.internal.corext.codemanipulation.GetterSetterUtil;
61 import org.eclipse.jdt.internal.corext.refactoring.Checks;
62 import org.eclipse.jdt.internal.corext.refactoring.CollectingSearchRequestor;
63 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor;
64 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
65 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
66 import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
67 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
68 import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory;
69 import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine;
70 import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
71 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
72 import org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange;
73 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
74 import org.eclipse.jdt.internal.corext.refactoring.changes.TextChangeCompatibility;
75 import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring;
76 import org.eclipse.jdt.internal.corext.refactoring.delegates.DelegateCreator;
77 import org.eclipse.jdt.internal.corext.refactoring.delegates.DelegateFieldCreator;
78 import org.eclipse.jdt.internal.corext.refactoring.delegates.DelegateMethodCreator;
79 import org.eclipse.jdt.internal.corext.refactoring.participants.JavaProcessors;
80 import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil;
81 import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
82 import org.eclipse.jdt.internal.corext.refactoring.tagging.IDelegateUpdating;
83 import org.eclipse.jdt.internal.corext.refactoring.tagging.IReferenceUpdating;
84 import org.eclipse.jdt.internal.corext.refactoring.tagging.ITextUpdating;
85 import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil;
86 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
87 import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager;
88 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
89 import org.eclipse.jdt.internal.corext.util.JdtFlags;
90 import org.eclipse.jdt.internal.corext.util.Messages;
91 import org.eclipse.jdt.internal.corext.util.SearchUtils;
92
93 import org.eclipse.jdt.ui.JavaElementLabels;
94
95 import org.eclipse.jdt.internal.ui.JavaPlugin;
96 import org.eclipse.jdt.internal.ui.refactoring.RefactoringSaveHelper;
97
98 public class RenameFieldProcessor extends JavaRenameProcessor implements IReferenceUpdating, ITextUpdating, IDelegateUpdating {
99
100     protected static final String JavaDoc ATTRIBUTE_TEXTUAL_MATCHES= "textual"; //$NON-NLS-1$
101
private static final String JavaDoc ATTRIBUTE_RENAME_GETTER= "getter"; //$NON-NLS-1$
102
private static final String JavaDoc ATTRIBUTE_RENAME_SETTER= "setter"; //$NON-NLS-1$
103
private static final String JavaDoc ATTRIBUTE_DELEGATE= "delegate"; //$NON-NLS-1$
104
private static final String JavaDoc ATTRIBUTE_DEPRECATE= "deprecate"; //$NON-NLS-1$
105

106     protected IField fField;
107     private SearchResultGroup[] fReferences;
108     private TextChangeManager fChangeManager;
109     protected boolean fUpdateReferences;
110     protected boolean fUpdateTextualMatches;
111     private boolean fRenameGetter;
112     private boolean fRenameSetter;
113     private boolean fIsComposite;
114     private GroupCategorySet fCategorySet;
115     private boolean fDelegateUpdating;
116     private boolean fDelegateDeprecation;
117
118     public static final String JavaDoc IDENTIFIER= "org.eclipse.jdt.ui.renameFieldProcessor"; //$NON-NLS-1$
119

120     /**
121      * Creates a new rename field processor.
122      * @param field the field, or <code>null</code> if invoked by scripting
123      */

124     public RenameFieldProcessor(IField field) {
125         this(field, new TextChangeManager(true), null);
126         fIsComposite= false;
127     }
128     
129     /**
130      * Creates a new rename field processor.
131      * <p>
132      * This constructor is only used by <code>RenameTypeProcessor</code>.
133      * </p>
134      * @param field the field
135      * @param manager the change manager
136      * @param categorySet the group category set
137      */

138     RenameFieldProcessor(IField field, TextChangeManager manager, GroupCategorySet categorySet) {
139         initialize(field);
140         fChangeManager= manager;
141         fCategorySet= categorySet;
142         fDelegateUpdating= false;
143         fDelegateDeprecation= true;
144         fIsComposite= true;
145     }
146
147     private void initialize(IField field) {
148         fField= field;
149         if (fField != null)
150             setNewElementName(fField.getElementName());
151         fUpdateReferences= true;
152         fUpdateTextualMatches= false;
153         
154         fRenameGetter= false;
155         fRenameSetter= false;
156     }
157
158     public String JavaDoc getIdentifier() {
159         return IDENTIFIER;
160     }
161     
162     public boolean isApplicable() throws CoreException {
163         return RefactoringAvailabilityTester.isRenameFieldAvailable(fField);
164     }
165     
166     public String JavaDoc getProcessorName() {
167         return RefactoringCoreMessages.RenameFieldRefactoring_name;
168     }
169     
170     protected String JavaDoc[] getAffectedProjectNatures() throws CoreException {
171         return JavaProcessors.computeAffectedNatures(fField);
172     }
173
174     public IField getField() {
175         return fField;
176     }
177
178     public Object JavaDoc[] getElements() {
179         return new Object JavaDoc[] { fField};
180     }
181     
182     protected RenameModifications computeRenameModifications() throws CoreException {
183         RenameModifications result= new RenameModifications();
184         result.rename(fField, new RenameArguments(getNewElementName(), getUpdateReferences()));
185         if (fRenameGetter) {
186             IMethod getter= getGetter();
187             if (getter != null) {
188                 result.rename(getter, new RenameArguments(getNewGetterName(), getUpdateReferences()));
189             }
190         }
191         if (fRenameSetter) {
192             IMethod setter= getSetter();
193             if (setter != null) {
194                 result.rename(setter, new RenameArguments(getNewSetterName(), getUpdateReferences()));
195             }
196         }
197         return result;
198     }
199     
200     protected IFile[] getChangedFiles() {
201         return ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits());
202     }
203     
204     //---- IRenameProcessor -------------------------------------
205

206     public final String JavaDoc getCurrentElementName(){
207         return fField.getElementName();
208     }
209     
210     public final String JavaDoc getCurrentElementQualifier(){
211         return JavaModelUtil.getFullyQualifiedName(fField.getDeclaringType());
212     }
213     
214     public RefactoringStatus checkNewElementName(String JavaDoc newName) throws CoreException {
215         Assert.isNotNull(newName, "new name"); //$NON-NLS-1$
216
RefactoringStatus result= Checks.checkFieldName(newName);
217
218         if (isInstanceField(fField) && (!Checks.startsWithLowerCase(newName)))
219             result.addWarning(fIsComposite
220                     ? Messages.format(RefactoringCoreMessages.RenameFieldRefactoring_should_start_lowercase2, new String JavaDoc[] { newName, fField.getDeclaringType().getElementName() })
221                     : RefactoringCoreMessages.RenameFieldRefactoring_should_start_lowercase);
222
223         if (Checks.isAlreadyNamed(fField, newName))
224             result.addError(fIsComposite
225                     ? Messages.format(RefactoringCoreMessages.RenameFieldRefactoring_another_name2, new String JavaDoc[] { newName, fField.getDeclaringType().getElementName() })
226                     : RefactoringCoreMessages.RenameFieldRefactoring_another_name,
227                     JavaStatusContext.create(fField));
228         
229         if (fField.getDeclaringType().getField(newName).exists())
230             result.addError(fIsComposite
231                     ? Messages.format(RefactoringCoreMessages.RenameFieldRefactoring_field_already_defined2, new String JavaDoc[] { newName, fField.getDeclaringType().getElementName() })
232                     : RefactoringCoreMessages.RenameFieldRefactoring_field_already_defined,
233                     JavaStatusContext.create(fField.getDeclaringType().getField(newName)));
234         return result;
235     }
236     
237     public Object JavaDoc getNewElement() {
238         return fField.getDeclaringType().getField(getNewElementName());
239     }
240     
241     //---- ITextUpdating2 ---------------------------------------------
242

243     public boolean canEnableTextUpdating() {
244         return true;
245     }
246     
247     public boolean getUpdateTextualMatches() {
248         return fUpdateTextualMatches;
249     }
250     
251     public void setUpdateTextualMatches(boolean update) {
252         fUpdateTextualMatches= update;
253     }
254     
255     //---- IReferenceUpdating -----------------------------------
256

257     public boolean canEnableUpdateReferences() {
258         return true;
259     }
260
261     public void setUpdateReferences(boolean update) {
262         fUpdateReferences= update;
263     }
264     
265     public boolean getUpdateReferences(){
266         return fUpdateReferences;
267     }
268         
269     //-- getter/setter --------------------------------------------------
270

271     /**
272      * @return Error message or <code>null</code> if getter can be renamed.
273      * @throws CoreException
274      */

275     public String JavaDoc canEnableGetterRenaming() throws CoreException{
276         if (fField.getDeclaringType().isInterface())
277             return getGetter() == null ? "": null; //$NON-NLS-1$
278

279         IMethod getter= getGetter();
280         if (getter == null)
281             return ""; //$NON-NLS-1$
282
final NullProgressMonitor monitor= new NullProgressMonitor();
283         if (MethodChecks.isVirtual(getter)) {
284             final ITypeHierarchy hierarchy= getter.getDeclaringType().newTypeHierarchy(monitor);
285             if (MethodChecks.isDeclaredInInterface(getter, hierarchy, monitor) != null || MethodChecks.overridesAnotherMethod(getter, hierarchy) != null)
286                 return RefactoringCoreMessages.RenameFieldRefactoring_declared_in_supertype;
287         }
288         return null;
289     }
290     
291     /**
292      * @return Error message or <code>null</code> if setter can be renamed.
293      * @throws CoreException
294      */

295     public String JavaDoc canEnableSetterRenaming() throws CoreException{
296         if (fField.getDeclaringType().isInterface())
297             return getSetter() == null ? "": null; //$NON-NLS-1$
298

299         IMethod setter= getSetter();
300         if (setter == null)
301             return ""; //$NON-NLS-1$
302
final NullProgressMonitor monitor= new NullProgressMonitor();
303         if (MethodChecks.isVirtual(setter)) {
304             final ITypeHierarchy hierarchy= setter.getDeclaringType().newTypeHierarchy(monitor);
305             if (MethodChecks.isDeclaredInInterface(setter, hierarchy, monitor) != null || MethodChecks.overridesAnotherMethod(setter, hierarchy) != null)
306                 return RefactoringCoreMessages.RenameFieldRefactoring_declared_in_supertype;
307         }
308         return null;
309     }
310     
311     public boolean getRenameGetter() {
312         return fRenameGetter;
313     }
314
315     public void setRenameGetter(boolean renameGetter) {
316         fRenameGetter= renameGetter;
317     }
318
319     public boolean getRenameSetter() {
320         return fRenameSetter;
321     }
322
323     public void setRenameSetter(boolean renameSetter) {
324         fRenameSetter= renameSetter;
325     }
326     
327     public IMethod getGetter() throws CoreException {
328         return GetterSetterUtil.getGetter(fField);
329     }
330     
331     public IMethod getSetter() throws CoreException {
332         return GetterSetterUtil.getSetter(fField);
333     }
334
335     public String JavaDoc getNewGetterName() throws CoreException {
336         IMethod primaryGetterCandidate= JavaModelUtil.findMethod(GetterSetterUtil.getGetterName(fField, new String JavaDoc[0]), new String JavaDoc[0], false, fField.getDeclaringType());
337         if (! JavaModelUtil.isBoolean(fField) || (primaryGetterCandidate != null && primaryGetterCandidate.exists()))
338             return GetterSetterUtil.getGetterName(fField.getJavaProject(), getNewElementName(), fField.getFlags(), JavaModelUtil.isBoolean(fField), null);
339         //bug 30906 describes why we need to look for other alternatives here
340
return GetterSetterUtil.getGetterName(fField.getJavaProject(), getNewElementName(), fField.getFlags(), false, null);
341     }
342
343     public String JavaDoc getNewSetterName() throws CoreException {
344         return GetterSetterUtil.getSetterName(fField.getJavaProject(), getNewElementName(), fField.getFlags(), JavaModelUtil.isBoolean(fField), null);
345     }
346     
347     // ------------------- IDelegateUpdating ----------------------
348

349     public boolean canEnableDelegateUpdating() {
350         return (getDelegateCount() > 0);
351     }
352
353     public boolean getDelegateUpdating() {
354         return fDelegateUpdating;
355     }
356
357     public void setDelegateUpdating(boolean update) {
358         fDelegateUpdating= update;
359     }
360
361     public void setDeprecateDelegates(boolean deprecate) {
362         fDelegateDeprecation= deprecate;
363     }
364
365     public boolean getDeprecateDelegates() {
366         return fDelegateDeprecation;
367     }
368
369     /**
370      * Returns the maximum number of delegates which can
371      * be created for the input elements of this refactoring.
372      *
373      * @return maximum number of delegates
374      */

375     public int getDelegateCount() {
376         int count= 0;
377         try {
378             if (RefactoringAvailabilityTester.isDelegateCreationAvailable(getField()))
379                 count++;
380             if (fRenameGetter && getGetter() != null)
381                 count++;
382             if (fRenameSetter && getSetter() != null)
383                 count++;
384         } catch (CoreException e) {
385             // no-op
386
}
387         return count;
388     }
389
390     public int getSaveMode() {
391         return RefactoringSaveHelper.SAVE_NON_JAVA_UPDATES;
392     }
393     
394     public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
395         IField primary= (IField) fField.getPrimaryElement();
396         if (primary == null || !primary.exists()) {
397             String JavaDoc message= Messages.format(RefactoringCoreMessages.RenameFieldRefactoring_deleted, fField.getCompilationUnit().getElementName());
398             return RefactoringStatus.createFatalErrorStatus(message);
399         }
400         fField= primary;
401
402         return Checks.checkIfCuBroken(fField);
403     }
404
405     protected RefactoringStatus doCheckFinalConditions(IProgressMonitor pm, CheckConditionsContext context) throws CoreException {
406         try{
407             pm.beginTask("", 18); //$NON-NLS-1$
408
pm.setTaskName(RefactoringCoreMessages.RenameFieldRefactoring_checking);
409             RefactoringStatus result= new RefactoringStatus();
410             result.merge(Checks.checkIfCuBroken(fField));
411             if (result.hasFatalError())
412                 return result;
413             result.merge(checkNewElementName(getNewElementName()));
414             pm.worked(1);
415             result.merge(checkEnclosingHierarchy());
416             pm.worked(1);
417             result.merge(checkNestedHierarchy(fField.getDeclaringType()));
418             pm.worked(1);
419             
420             if (fUpdateReferences){
421                 pm.setTaskName(RefactoringCoreMessages.RenameFieldRefactoring_searching);
422                 fReferences= getReferences(new SubProgressMonitor(pm, 3), result);
423                 pm.setTaskName(RefactoringCoreMessages.RenameFieldRefactoring_checking);
424             } else {
425                 fReferences= new SearchResultGroup[0];
426                 pm.worked(3);
427             }
428             
429             if (fUpdateReferences)
430                 result.merge(analyzeAffectedCompilationUnits());
431             else
432                 Checks.checkCompileErrorsInAffectedFile(result, fField.getResource());
433                 
434             if (getGetter() != null && fRenameGetter){
435                 result.merge(checkAccessor(new SubProgressMonitor(pm, 1), getGetter(), getNewGetterName()));
436                 result.merge(Checks.checkIfConstructorName(getGetter(), getNewGetterName(), fField.getDeclaringType().getElementName()));
437             } else {
438                 pm.worked(1);
439             }
440                 
441             if (getSetter() != null && fRenameSetter){
442                 result.merge(checkAccessor(new SubProgressMonitor(pm, 1), getSetter(), getNewSetterName()));
443                 result.merge(Checks.checkIfConstructorName(getSetter(), getNewSetterName(), fField.getDeclaringType().getElementName()));
444             } else {
445                 pm.worked(1);
446             }
447             
448             result.merge(createChanges(new SubProgressMonitor(pm, 10)));
449             if (result.hasFatalError())
450                 return result;
451             
452             return result;
453         } finally{
454             pm.done();
455         }
456     }
457     
458     //----------
459
private RefactoringStatus checkAccessor(IProgressMonitor pm, IMethod existingAccessor, String JavaDoc newAccessorName) throws CoreException{
460         RefactoringStatus result= new RefactoringStatus();
461         result.merge(checkAccessorDeclarations(pm, existingAccessor));
462         result.merge(checkNewAccessor(existingAccessor, newAccessorName));
463         return result;
464     }
465     
466     private RefactoringStatus checkNewAccessor(IMethod existingAccessor, String JavaDoc newAccessorName) throws CoreException{
467         RefactoringStatus result= new RefactoringStatus();
468         IMethod accessor= JavaModelUtil.findMethod(newAccessorName, existingAccessor.getParameterTypes(), false, fField.getDeclaringType());
469         if (accessor == null || !accessor.exists())
470             return null;
471     
472         String JavaDoc message= Messages.format(RefactoringCoreMessages.RenameFieldRefactoring_already_exists,
473                 new String JavaDoc[]{JavaElementUtil.createMethodSignature(accessor), JavaModelUtil.getFullyQualifiedName(fField.getDeclaringType())});
474         result.addError(message, JavaStatusContext.create(accessor));
475         return result;
476     }
477     
478     private RefactoringStatus checkAccessorDeclarations(IProgressMonitor pm, IMethod existingAccessor) throws CoreException{
479         RefactoringStatus result= new RefactoringStatus();
480         SearchPattern pattern= SearchPattern.createPattern(existingAccessor, IJavaSearchConstants.DECLARATIONS, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
481         IJavaSearchScope scope= SearchEngine.createHierarchyScope(fField.getDeclaringType());
482         SearchResultGroup[] groupDeclarations= RefactoringSearchEngine.search(pattern, scope, pm, result);
483         Assert.isTrue(groupDeclarations.length > 0);
484         if (groupDeclarations.length != 1){
485             String JavaDoc message= Messages.format(RefactoringCoreMessages.RenameFieldRefactoring_overridden,
486                                 JavaElementUtil.createMethodSignature(existingAccessor));
487             result.addError(message);
488         } else {
489             SearchResultGroup group= groupDeclarations[0];
490             Assert.isTrue(group.getSearchResults().length > 0);
491             if (group.getSearchResults().length != 1){
492                 String JavaDoc message= Messages.format(RefactoringCoreMessages.RenameFieldRefactoring_overridden_or_overrides,
493                                     JavaElementUtil.createMethodSignature(existingAccessor));
494                 result.addError(message);
495             }
496         }
497         return result;
498     }
499     
500     private static boolean isInstanceField(IField field) throws CoreException{
501         if (JavaModelUtil.isInterfaceOrAnnotation(field.getDeclaringType()))
502             return false;
503         else
504             return ! JdtFlags.isStatic(field);
505     }
506     
507     private RefactoringStatus checkNestedHierarchy(IType type) throws CoreException {
508         IType[] nestedTypes= type.getTypes();
509         if (nestedTypes == null)
510             return null;
511         RefactoringStatus result= new RefactoringStatus();
512         for (int i= 0; i < nestedTypes.length; i++){
513             IField otherField= nestedTypes[i].getField(getNewElementName());
514             if (otherField.exists()){
515                 String JavaDoc msg= Messages.format(
516                     RefactoringCoreMessages.RenameFieldRefactoring_hiding,
517                     new String JavaDoc[]{fField.getElementName(), getNewElementName(), JavaModelUtil.getFullyQualifiedName(nestedTypes[i])});
518                 result.addWarning(msg, JavaStatusContext.create(otherField));
519             }
520             result.merge(checkNestedHierarchy(nestedTypes[i]));
521         }
522         return result;
523     }
524     
525     private RefactoringStatus checkEnclosingHierarchy() {
526         IType current= fField.getDeclaringType();
527         if (Checks.isTopLevel(current))
528             return null;
529         RefactoringStatus result= new RefactoringStatus();
530         while (current != null){
531             IField otherField= current.getField(getNewElementName());
532             if (otherField.exists()){
533                 String JavaDoc msg= Messages.format(RefactoringCoreMessages.RenameFieldRefactoring_hiding2,
534                                                                             new String JavaDoc[]{getNewElementName(), JavaModelUtil.getFullyQualifiedName(current), otherField.getElementName()});
535                 result.addWarning(msg, JavaStatusContext.create(otherField));
536             }
537             current= current.getDeclaringType();
538         }
539         return result;
540     }
541     
542     /*
543      * (non java-doc)
544      * Analyzes all compilation units in which type is referenced
545      */

546     private RefactoringStatus analyzeAffectedCompilationUnits() throws CoreException{
547         RefactoringStatus result= new RefactoringStatus();
548         fReferences= Checks.excludeCompilationUnits(fReferences, result);
549         if (result.hasFatalError())
550             return result;
551         
552         result.merge(Checks.checkCompileErrorsInAffectedFiles(fReferences));
553         return result;
554     }
555     
556     private SearchPattern createSearchPattern(){
557         return SearchPattern.createPattern(fField, IJavaSearchConstants.REFERENCES);
558     }
559     
560     private IJavaSearchScope createRefactoringScope() throws CoreException{
561         return RefactoringScopeFactory.create(fField);
562     }
563     
564     private SearchResultGroup[] getReferences(IProgressMonitor pm, RefactoringStatus status) throws CoreException{
565         return RefactoringSearchEngine.search(createSearchPattern(), createRefactoringScope(), pm, status);
566     }
567
568     public Change createChange(IProgressMonitor monitor) throws CoreException {
569         try {
570             monitor.beginTask(RefactoringCoreMessages.RenameFieldRefactoring_checking, 1);
571             final TextChange[] changes= fChangeManager.getAllChanges();
572             final List JavaDoc list= new ArrayList JavaDoc(changes.length);
573             list.addAll(Arrays.asList(changes));
574             String JavaDoc project= null;
575             IJavaProject javaProject= fField.getJavaProject();
576             if (javaProject != null)
577                 project= javaProject.getElementName();
578             int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE;
579             try {
580                 if (!Flags.isPrivate(fField.getFlags()))
581                     flags|= RefactoringDescriptor.MULTI_CHANGE;
582             } catch (JavaModelException exception) {
583                 JavaPlugin.log(exception);
584             }
585             final IType declaring= fField.getDeclaringType();
586             try {
587                 if (declaring.isAnonymous() || declaring.isLocal())
588                     flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
589             } catch (JavaModelException exception) {
590                 JavaPlugin.log(exception);
591             }
592             final String JavaDoc description= Messages.format(RefactoringCoreMessages.RenameFieldRefactoring_descriptor_description_short, fField.getElementName());
593             final String JavaDoc header= Messages.format(RefactoringCoreMessages.RenameFieldProcessor_descriptor_description, new String JavaDoc[] { fField.getElementName(), JavaElementLabels.getElementLabel(fField.getParent(), JavaElementLabels.ALL_FULLY_QUALIFIED), getNewElementName()});
594             final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header);
595             if (fRenameGetter)
596                 comment.addSetting(RefactoringCoreMessages.RenameFieldRefactoring_setting_rename_getter);
597             if (fRenameSetter)
598                 comment.addSetting(RefactoringCoreMessages.RenameFieldRefactoring_setting_rename_settter);
599             final RenameJavaElementDescriptor descriptor= new RenameJavaElementDescriptor(IJavaRefactorings.RENAME_FIELD);
600             descriptor.setProject(project);
601             descriptor.setDescription(description);
602             descriptor.setComment(comment.asString());
603             descriptor.setFlags(flags);
604             descriptor.setJavaElement(fField);
605             descriptor.setNewName(getNewElementName());
606             descriptor.setUpdateReferences(fUpdateReferences);
607             descriptor.setUpdateTextualOccurrences(fUpdateTextualMatches);
608             descriptor.setRenameGetters(fRenameGetter);
609             descriptor.setRenameSetters(fRenameSetter);
610             descriptor.setKeepOriginal(fDelegateUpdating);
611             descriptor.setDeprecateDelegate(fDelegateDeprecation);
612             return new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.RenameFieldRefactoring_change_name, (Change[]) list.toArray(new Change[list.size()]));
613         } finally {
614             monitor.done();
615         }
616     }
617
618     private RefactoringStatus createChanges(IProgressMonitor pm) throws CoreException {
619         pm.beginTask(RefactoringCoreMessages.RenameFieldRefactoring_checking, 10);
620         RefactoringStatus result= new RefactoringStatus();
621         if (!fIsComposite)
622             fChangeManager.clear();
623
624         // Delegate creation requires ASTRewrite which
625
// creates a new change -> do this first.
626
if (fDelegateUpdating)
627             result.merge(addDelegates());
628         
629         addDeclarationUpdate();
630         
631         if (fUpdateReferences) {
632             addReferenceUpdates(new SubProgressMonitor(pm, 1));
633             result.merge(analyzeRenameChanges(new SubProgressMonitor(pm, 2)));
634             if (result.hasFatalError())
635                 return result;
636         } else {
637             pm.worked(3);
638         }
639         
640         if (getGetter() != null && fRenameGetter) {
641             addGetterOccurrences(new SubProgressMonitor(pm, 1), result);
642         } else {
643             pm.worked(1);
644         }
645                     
646         if (getSetter() != null && fRenameSetter) {
647             addSetterOccurrences(new SubProgressMonitor(pm, 1), result);
648         } else {
649             pm.worked(1);
650         }
651
652         if (fUpdateTextualMatches) {
653             addTextMatches(new SubProgressMonitor(pm, 5));
654         } else {
655             pm.worked(5);
656         }
657         pm.done();
658         return result;
659     }
660
661     private void addDeclarationUpdate() throws CoreException {
662         ISourceRange nameRange= fField.getNameRange();
663         TextEdit textEdit= new ReplaceEdit(nameRange.getOffset(), nameRange.getLength(), getNewElementName());
664         ICompilationUnit cu= fField.getCompilationUnit();
665         String JavaDoc groupName= RefactoringCoreMessages.RenameFieldRefactoring_Update_field_declaration;
666         addTextEdit(fChangeManager.get(cu), groupName, textEdit);
667     }
668
669     private RefactoringStatus addDelegates() throws JavaModelException, CoreException {
670
671         RefactoringStatus status= new RefactoringStatus();
672         CompilationUnitRewrite rewrite= new CompilationUnitRewrite(fField.getCompilationUnit());
673         rewrite.setResolveBindings(true);
674
675         // add delegate for the field
676
if (RefactoringAvailabilityTester.isDelegateCreationAvailable(fField)) {
677             FieldDeclaration fieldDeclaration= ASTNodeSearchUtil.getFieldDeclarationNode(fField, rewrite.getRoot());
678             if (fieldDeclaration.fragments().size() > 1) {
679                 status.addWarning(Messages.format(RefactoringCoreMessages.DelegateCreator_cannot_create_field_delegate_more_than_one_fragment, fField
680                         .getElementName()), JavaStatusContext.create(fField));
681             } else if (((VariableDeclarationFragment) fieldDeclaration.fragments().get(0)).getInitializer() == null) {
682                 status.addWarning(Messages.format(RefactoringCoreMessages.DelegateCreator_cannot_create_field_delegate_no_initializer, fField
683                         .getElementName()), JavaStatusContext.create(fField));
684             } else {
685                 DelegateFieldCreator creator= new DelegateFieldCreator();
686                 creator.setDeclareDeprecated(fDelegateDeprecation);
687                 creator.setDeclaration(fieldDeclaration);
688                 creator.setNewElementName(getNewElementName());
689                 creator.setSourceRewrite(rewrite);
690                 creator.prepareDelegate();
691                 creator.createEdit();
692             }
693         }
694
695         // add delegates for getter and setter methods
696
// there may be getters even if the field is static final
697
if (getGetter() != null && fRenameGetter)
698             addMethodDelegate(getGetter(), getNewGetterName(), rewrite);
699         if (getSetter() != null && fRenameSetter)
700             addMethodDelegate(getSetter(), getNewSetterName(), rewrite);
701
702         final CompilationUnitChange change= rewrite.createChange();
703         if (change != null) {
704             change.setKeepPreviewEdits(true);
705             fChangeManager.manage(fField.getCompilationUnit(), change);
706         }
707
708         return status;
709     }
710
711     private void addMethodDelegate(IMethod getter, String JavaDoc newName, CompilationUnitRewrite rewrite) throws JavaModelException {
712         MethodDeclaration declaration= ASTNodeSearchUtil.getMethodDeclarationNode(getter, rewrite.getRoot());
713         DelegateCreator creator= new DelegateMethodCreator();
714         creator.setDeclareDeprecated(fDelegateDeprecation);
715         creator.setDeclaration(declaration);
716         creator.setNewElementName(newName);
717         creator.setSourceRewrite(rewrite);
718         creator.prepareDelegate();
719         creator.createEdit();
720     }
721
722     private void addTextEdit(TextChange change, String JavaDoc groupName, TextEdit textEdit) {
723         if (fIsComposite)
724             TextChangeCompatibility.addTextEdit(change, groupName, textEdit, fCategorySet);
725         else
726             TextChangeCompatibility.addTextEdit(change, groupName, textEdit);
727
728     }
729
730     private void addReferenceUpdates(IProgressMonitor pm) {
731         pm.beginTask("", fReferences.length); //$NON-NLS-1$
732
String JavaDoc editName= RefactoringCoreMessages.RenameFieldRefactoring_Update_field_reference;
733         for (int i= 0; i < fReferences.length; i++){
734             ICompilationUnit cu= fReferences[i].getCompilationUnit();
735             if (cu == null)
736                 continue;
737             SearchMatch[] results= fReferences[i].getSearchResults();
738             for (int j= 0; j < results.length; j++){
739                 addTextEdit(fChangeManager.get(cu), editName, createTextChange(results[j]));
740             }
741             pm.worked(1);
742         }
743     }
744     
745     private TextEdit createTextChange(SearchMatch match) {
746         return new ReplaceEdit(match.getOffset(), match.getLength(), getNewElementName());
747     }
748     
749     private void addGetterOccurrences(IProgressMonitor pm, RefactoringStatus status) throws CoreException {
750         addAccessorOccurrences(pm, getGetter(), RefactoringCoreMessages.RenameFieldRefactoring_Update_getter_occurrence, getNewGetterName(), status);
751     }
752     
753     private void addSetterOccurrences(IProgressMonitor pm, RefactoringStatus status) throws CoreException {
754         addAccessorOccurrences(pm, getSetter(), RefactoringCoreMessages.RenameFieldRefactoring_Update_setter_occurrence, getNewSetterName(), status);
755     }
756
757     private void addAccessorOccurrences(IProgressMonitor pm, IMethod accessor, String JavaDoc editName, String JavaDoc newAccessorName, RefactoringStatus status) throws CoreException {
758         Assert.isTrue(accessor.exists());
759         
760         IJavaSearchScope scope= RefactoringScopeFactory.create(accessor);
761         SearchPattern pattern= SearchPattern.createPattern(accessor, IJavaSearchConstants.ALL_OCCURRENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
762         SearchResultGroup[] groupedResults= RefactoringSearchEngine.search(
763             pattern, scope, new MethodOccurenceCollector(accessor.getElementName()), pm, status);
764         
765         for (int i= 0; i < groupedResults.length; i++) {
766             ICompilationUnit cu= groupedResults[i].getCompilationUnit();
767             if (cu == null)
768                 continue;
769             SearchMatch[] results= groupedResults[i].getSearchResults();
770             for (int j= 0; j < results.length; j++){
771                 SearchMatch searchResult= results[j];
772                 TextEdit edit= new ReplaceEdit(searchResult.getOffset(), searchResult.getLength(), newAccessorName);
773                 addTextEdit(fChangeManager.get(cu), editName, edit);
774             }
775         }
776     }
777     
778     private void addTextMatches(IProgressMonitor pm) throws CoreException {
779         TextMatchUpdater.perform(pm, createRefactoringScope(), this, fChangeManager, fReferences);
780     }
781     
782     //----------------
783
private RefactoringStatus analyzeRenameChanges(IProgressMonitor pm) throws CoreException {
784         ICompilationUnit[] newWorkingCopies= null;
785         WorkingCopyOwner newWCOwner= new WorkingCopyOwner() { /* must subclass */ };
786         try {
787             pm.beginTask("", 2); //$NON-NLS-1$
788
RefactoringStatus result= new RefactoringStatus();
789             SearchResultGroup[] oldReferences= fReferences;
790
791             List JavaDoc compilationUnitsToModify= new ArrayList JavaDoc();
792             if (fIsComposite) {
793                 // limited change set, no accessors.
794
for (int i= 0; i < oldReferences.length; i++)
795                     compilationUnitsToModify.add(oldReferences[i].getCompilationUnit());
796                 compilationUnitsToModify.add(fField.getCompilationUnit());
797             } else {
798                 // include all cus, including accessors
799
compilationUnitsToModify.addAll(Arrays.asList(fChangeManager.getAllCompilationUnits()));
800             }
801             
802             newWorkingCopies= RenameAnalyzeUtil.createNewWorkingCopies((ICompilationUnit[]) compilationUnitsToModify.toArray(new ICompilationUnit[compilationUnitsToModify.size()]),
803                     fChangeManager, newWCOwner, new SubProgressMonitor(pm, 1));
804             
805             SearchResultGroup[] newReferences= getNewReferences(new SubProgressMonitor(pm, 1), result, newWCOwner, newWorkingCopies);
806             result.merge(RenameAnalyzeUtil.analyzeRenameChanges2(fChangeManager, oldReferences, newReferences, getNewElementName()));
807             return result;
808         } finally{
809             pm.done();
810             if (newWorkingCopies != null){
811                 for (int i= 0; i < newWorkingCopies.length; i++) {
812                     newWorkingCopies[i].discardWorkingCopy();
813                 }
814             }
815         }
816     }
817
818     private SearchResultGroup[] getNewReferences(IProgressMonitor pm, RefactoringStatus status, WorkingCopyOwner owner, ICompilationUnit[] newWorkingCopies) throws CoreException {
819         pm.beginTask("", 2); //$NON-NLS-1$
820
ICompilationUnit declaringCuWorkingCopy= RenameAnalyzeUtil.findWorkingCopyForCu(newWorkingCopies, fField.getCompilationUnit());
821         if (declaringCuWorkingCopy == null)
822             return new SearchResultGroup[0];
823         
824         IField field= getFieldInWorkingCopy(declaringCuWorkingCopy, getNewElementName());
825         if (field == null || ! field.exists())
826             return new SearchResultGroup[0];
827         
828         CollectingSearchRequestor requestor= null;
829         if (fDelegateUpdating && RefactoringAvailabilityTester.isDelegateCreationAvailable(getField())) {
830             // There will be two new matches inside the delegate (the invocation
831
// and the javadoc) which are OK and must not be reported.
832
final IField oldField= getFieldInWorkingCopy(declaringCuWorkingCopy, getCurrentElementName());
833             requestor= new CollectingSearchRequestor() {
834                 public void acceptSearchMatch(SearchMatch match) throws CoreException {
835                     if (!oldField.equals(match.getElement()))
836                         super.acceptSearchMatch(match);
837                 }
838             };
839         } else
840             requestor= new CollectingSearchRequestor();
841         
842         SearchPattern newPattern= SearchPattern.createPattern(field, IJavaSearchConstants.REFERENCES);
843         return RefactoringSearchEngine.search(newPattern, owner, createRefactoringScope(), requestor, new SubProgressMonitor(pm, 1), status);
844     }
845     
846     private IField getFieldInWorkingCopy(ICompilationUnit newWorkingCopyOfDeclaringCu, String JavaDoc elementName) throws CoreException{
847         IType type= fField.getDeclaringType();
848         IType typeWc= (IType) JavaModelUtil.findInCompilationUnit(newWorkingCopyOfDeclaringCu, type);
849         if (typeWc == null)
850             return null;
851         
852         return typeWc.getField(elementName);
853     }
854
855     public RefactoringStatus initialize(RefactoringArguments arguments) {
856         if (arguments instanceof JavaRefactoringArguments) {
857             final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments;
858             final String JavaDoc handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT);
859             if (handle != null) {
860                 final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false);
861                 if (element == null || !element.exists() || element.getElementType() != IJavaElement.FIELD)
862                     return ScriptableRefactoring.createInputFatalStatus(element, getRefactoring().getName(), IJavaRefactorings.RENAME_FIELD);
863                 else
864                     fField= (IField) element;
865             } else
866                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT));
867             final String JavaDoc name= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_NAME);
868             if (name != null && !"".equals(name)) //$NON-NLS-1$
869
setNewElementName(name);
870             else
871                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_NAME));
872             final String JavaDoc references= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_REFERENCES);
873             if (references != null) {
874                 fUpdateReferences= Boolean.valueOf(references).booleanValue();
875             } else
876                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_REFERENCES));
877             final String JavaDoc matches= extended.getAttribute(ATTRIBUTE_TEXTUAL_MATCHES);
878             if (matches != null) {
879                 fUpdateTextualMatches= Boolean.valueOf(matches).booleanValue();
880             } else
881                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_TEXTUAL_MATCHES));
882             final String JavaDoc getters= extended.getAttribute(ATTRIBUTE_RENAME_GETTER);
883             if (getters != null)
884                 fRenameGetter= Boolean.valueOf(getters).booleanValue();
885             else
886                 fRenameGetter= false;
887             final String JavaDoc setters= extended.getAttribute(ATTRIBUTE_RENAME_SETTER);
888             if (setters != null)
889                 fRenameSetter= Boolean.valueOf(setters).booleanValue();
890             else
891                 fRenameSetter= false;
892             final String JavaDoc delegate= extended.getAttribute(ATTRIBUTE_DELEGATE);
893             if (delegate != null) {
894                 fDelegateUpdating= Boolean.valueOf(delegate).booleanValue();
895             } else
896                 fDelegateUpdating= false;
897             final String JavaDoc deprecate= extended.getAttribute(ATTRIBUTE_DEPRECATE);
898             if (deprecate != null) {
899                 fDelegateDeprecation= Boolean.valueOf(deprecate).booleanValue();
900             } else
901                 fDelegateDeprecation= false;
902         } else
903             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
904         return new RefactoringStatus();
905     }
906
907     /**
908      * {@inheritDoc}
909      */

910     public String JavaDoc getDelegateUpdatingTitle(boolean plural) {
911         if (plural)
912             return RefactoringCoreMessages.DelegateFieldCreator_keep_original_renamed_plural;
913         else
914             return RefactoringCoreMessages.DelegateFieldCreator_keep_original_renamed_singular;
915     }
916 }
917
Popular Tags