KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > code > ConvertAnonymousToNestedRefactoring


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  * N.Metchev@teamphone.com - contributed fixes for
11  * - convert anonymous to nested should sometimes declare class as static [refactoring]
12  * (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=43360)
13  * - Convert anonymous to nested: should show error if field form outer anonymous type is references [refactoring]
14  * (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=48282)
15  *******************************************************************************/

16 package org.eclipse.jdt.internal.corext.refactoring.code;
17
18 import java.util.ArrayList JavaDoc;
19 import java.util.Arrays JavaDoc;
20 import java.util.Collections JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.HashSet JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.Map JavaDoc;
26 import java.util.Set JavaDoc;
27 import java.util.StringTokenizer JavaDoc;
28
29 import org.eclipse.core.runtime.Assert;
30 import org.eclipse.core.runtime.CoreException;
31 import org.eclipse.core.runtime.IProgressMonitor;
32
33 import org.eclipse.ltk.core.refactoring.Change;
34 import org.eclipse.ltk.core.refactoring.RefactoringChangeDescriptor;
35 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
36 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
37 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
38
39 import org.eclipse.jdt.core.ICompilationUnit;
40 import org.eclipse.jdt.core.IJavaElement;
41 import org.eclipse.jdt.core.IJavaProject;
42 import org.eclipse.jdt.core.JavaModelException;
43 import org.eclipse.jdt.core.dom.AST;
44 import org.eclipse.jdt.core.dom.ASTNode;
45 import org.eclipse.jdt.core.dom.ASTVisitor;
46 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
47 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
48 import org.eclipse.jdt.core.dom.Assignment;
49 import org.eclipse.jdt.core.dom.BodyDeclaration;
50 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
51 import org.eclipse.jdt.core.dom.CompilationUnit;
52 import org.eclipse.jdt.core.dom.Expression;
53 import org.eclipse.jdt.core.dom.FieldAccess;
54 import org.eclipse.jdt.core.dom.FieldDeclaration;
55 import org.eclipse.jdt.core.dom.IBinding;
56 import org.eclipse.jdt.core.dom.IMethodBinding;
57 import org.eclipse.jdt.core.dom.ITypeBinding;
58 import org.eclipse.jdt.core.dom.IVariableBinding;
59 import org.eclipse.jdt.core.dom.Initializer;
60 import org.eclipse.jdt.core.dom.Javadoc;
61 import org.eclipse.jdt.core.dom.MethodDeclaration;
62 import org.eclipse.jdt.core.dom.Modifier;
63 import org.eclipse.jdt.core.dom.Name;
64 import org.eclipse.jdt.core.dom.ParameterizedType;
65 import org.eclipse.jdt.core.dom.QualifiedName;
66 import org.eclipse.jdt.core.dom.SimpleName;
67 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
68 import org.eclipse.jdt.core.dom.Statement;
69 import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
70 import org.eclipse.jdt.core.dom.SuperFieldAccess;
71 import org.eclipse.jdt.core.dom.Type;
72 import org.eclipse.jdt.core.dom.TypeDeclaration;
73 import org.eclipse.jdt.core.dom.TypeParameter;
74 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
75 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
76 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
77 import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
78 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
79
80 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
81 import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
82 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
83 import org.eclipse.jdt.internal.corext.dom.Bindings;
84 import org.eclipse.jdt.internal.corext.dom.LinkedNodeFinder;
85 import org.eclipse.jdt.internal.corext.dom.NodeFinder;
86 import org.eclipse.jdt.internal.corext.fix.LinkedProposalModel;
87 import org.eclipse.jdt.internal.corext.fix.LinkedProposalPositionGroup;
88 import org.eclipse.jdt.internal.corext.refactoring.Checks;
89 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor;
90 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
91 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
92 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
93 import org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange;
94 import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
95 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
96 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
97 import org.eclipse.jdt.internal.corext.util.JdtFlags;
98 import org.eclipse.jdt.internal.corext.util.Messages;
99
100 import org.eclipse.jdt.ui.CodeGeneration;
101 import org.eclipse.jdt.ui.JavaElementLabels;
102
103 import org.eclipse.jdt.internal.ui.JavaPlugin;
104 import org.eclipse.jdt.internal.ui.text.correction.ModifierCorrectionSubProcessor;
105 import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider;
106
107 public class ConvertAnonymousToNestedRefactoring extends ScriptableRefactoring {
108
109     private static final String JavaDoc ATTRIBUTE_VISIBILITY= "visibility"; //$NON-NLS-1$
110
private static final String JavaDoc ATTRIBUTE_FINAL= "final"; //$NON-NLS-1$
111
private static final String JavaDoc ATTRIBUTE_STATIC= "static"; //$NON-NLS-1$
112

113     private static final String JavaDoc KEY_TYPE_NAME= "type_name"; //$NON-NLS-1$
114
private static final String JavaDoc KEY_PARAM_NAME_EXT= "param_name_ext"; //$NON-NLS-1$
115
private static final String JavaDoc KEY_PARAM_NAME_CONST= "param_name_const"; //$NON-NLS-1$
116
private static final String JavaDoc KEY_FIELD_NAME_EXT= "field_name_ext"; //$NON-NLS-1$
117

118     public static class TypeVariableFinder extends ASTVisitor {
119
120         private final Map JavaDoc fBindings= new HashMap JavaDoc();
121         private final List JavaDoc fFound= new ArrayList JavaDoc();
122         
123         public final boolean visit(final SimpleName node) {
124             Assert.isNotNull(node);
125             final ITypeBinding binding= node.resolveTypeBinding();
126             if (binding != null && binding.isTypeVariable() && !fBindings.containsKey(binding.getKey())) {
127                 fBindings.put(binding.getKey(), binding);
128                 fFound.add(binding);
129             }
130             return true;
131         }
132
133         public final ITypeBinding[] getResult() {
134             final ITypeBinding[] result= new ITypeBinding[fFound.size()];
135             fFound.toArray(result);
136             return result;
137         }
138     }
139
140     private int fSelectionStart;
141     private int fSelectionLength;
142     private ICompilationUnit fCu;
143
144     private int fVisibility; /* see Modifier */
145     private boolean fDeclareFinal= true;
146     private boolean fDeclareStatic;
147     private String JavaDoc fClassName= ""; //$NON-NLS-1$
148

149     private CompilationUnit fCompilationUnitNode;
150     private AnonymousClassDeclaration fAnonymousInnerClassNode;
151     private Set JavaDoc fClassNamesUsed;
152     private boolean fSelfInitializing= false;
153     
154     private LinkedProposalModel fLinkedProposalModel;
155
156     /**
157      * Creates a new convert anonymous to nested refactoring
158      * @param unit the compilation unit, or <code>null</code> if invoked by scripting
159      * @param selectionStart
160      * @param selectionLength
161      */

162     public ConvertAnonymousToNestedRefactoring(ICompilationUnit unit, int selectionStart, int selectionLength) {
163         Assert.isTrue(selectionStart >= 0);
164         Assert.isTrue(selectionLength >= 0);
165         Assert.isTrue(unit == null || unit.exists());
166         fSelectionStart= selectionStart;
167         fSelectionLength= selectionLength;
168         fCu= unit;
169         fAnonymousInnerClassNode= null;
170         fCompilationUnitNode= null;
171     }
172     
173     public ConvertAnonymousToNestedRefactoring(AnonymousClassDeclaration declaration) {
174         Assert.isTrue(declaration != null);
175         
176         ASTNode astRoot= declaration.getRoot();
177         Assert.isTrue(astRoot instanceof CompilationUnit);
178         fCompilationUnitNode= (CompilationUnit) astRoot;
179         
180         IJavaElement javaElement= fCompilationUnitNode.getJavaElement();
181         Assert.isTrue(javaElement instanceof ICompilationUnit);
182         
183         fCu= (ICompilationUnit) javaElement;
184         fSelectionStart= declaration.getStartPosition();
185         fSelectionLength= declaration.getLength();
186     }
187     
188     public void setLinkedProposalModel(LinkedProposalModel linkedProposalModel) {
189         fLinkedProposalModel= linkedProposalModel;
190     }
191
192     public int[] getAvailableVisibilities() {
193         if (isLocalInnerType()) {
194             return new int[] { Modifier.NONE };
195         } else {
196             return new int[] { Modifier.PUBLIC, Modifier.PROTECTED, Modifier.NONE, Modifier.PRIVATE };
197         }
198     }
199
200     public boolean isLocalInnerType() {
201         return ASTNodes.getParent(ASTNodes.getParent(fAnonymousInnerClassNode, AbstractTypeDeclaration.class), ASTNode.ANONYMOUS_CLASS_DECLARATION) != null;
202     }
203
204     public int getVisibility() {
205         return fVisibility;
206     }
207
208     public void setVisibility(int visibility) {
209         Assert.isTrue(visibility == Modifier.PRIVATE || visibility == Modifier.NONE || visibility == Modifier.PROTECTED || visibility == Modifier.PUBLIC);
210         fVisibility= visibility;
211     }
212
213     public void setClassName(String JavaDoc className) {
214         Assert.isNotNull(className);
215         fClassName= className;
216     }
217
218     public boolean canEnableSettingFinal() {
219         return true;
220     }
221
222     public boolean getDeclareFinal() {
223         return fDeclareFinal;
224     }
225     
226     public boolean getDeclareStatic() {
227         return fDeclareStatic;
228     }
229     
230     public void setDeclareFinal(boolean declareFinal) {
231         fDeclareFinal= declareFinal;
232     }
233
234     public void setDeclareStatic(boolean declareStatic) {
235         fDeclareStatic= declareStatic;
236     }
237
238     public String JavaDoc getName() {
239         return RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_name;
240     }
241     
242     private boolean useThisForFieldAccess() {
243         return StubUtility.useThisForFieldAccess(fCu.getJavaProject());
244     }
245     
246     private boolean doAddComments() {
247         return StubUtility.doAddComments(fCu.getJavaProject());
248     }
249     
250     public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
251         RefactoringStatus result= Checks.validateModifiesFiles(
252             ResourceUtil.getFiles(new ICompilationUnit[]{fCu}),
253             getValidationContext());
254         if (result.hasFatalError())
255             return result;
256
257         initAST(pm);
258
259         if (fAnonymousInnerClassNode == null)
260             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_place_caret);
261         if (!fSelfInitializing)
262             initializeDefaults();
263         if (getSuperConstructorBinding() == null)
264             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_compile_errors);
265         if (getSuperTypeBinding().isLocal())
266             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_extends_local_class);
267         return new RefactoringStatus();
268     }
269
270     private void initializeDefaults() {
271         fVisibility= isLocalInnerType() ? Modifier.NONE : Modifier.PRIVATE;
272         fDeclareStatic = mustInnerClassBeStatic();
273     }
274
275     private void initAST(IProgressMonitor pm) {
276         if (fCompilationUnitNode == null) {
277             fCompilationUnitNode= RefactoringASTParser.parseWithASTProvider(fCu, true, pm);
278         }
279         if (fAnonymousInnerClassNode == null) {
280             fAnonymousInnerClassNode= getAnonymousInnerClass(NodeFinder.perform(fCompilationUnitNode, fSelectionStart, fSelectionLength));
281         }
282         if (fAnonymousInnerClassNode != null) {
283             final AbstractTypeDeclaration declaration= (AbstractTypeDeclaration) ASTNodes.getParent(fAnonymousInnerClassNode, AbstractTypeDeclaration.class);
284             if (declaration instanceof TypeDeclaration) {
285                 final AbstractTypeDeclaration[] nested= ((TypeDeclaration) declaration).getTypes();
286                 fClassNamesUsed= new HashSet JavaDoc(nested.length);
287                 for (int index= 0; index < nested.length; index++)
288                     fClassNamesUsed.add(nested[index].getName().getIdentifier());
289             } else
290                 fClassNamesUsed= Collections.EMPTY_SET;
291         }
292     }
293
294     private static AnonymousClassDeclaration getAnonymousInnerClass(ASTNode node) {
295         if (node == null)
296             return null;
297         if (node instanceof AnonymousClassDeclaration)
298             return (AnonymousClassDeclaration)node;
299         if (node instanceof ClassInstanceCreation) {
300             AnonymousClassDeclaration anon= ((ClassInstanceCreation)node).getAnonymousClassDeclaration();
301             if (anon != null)
302                 return anon;
303         }
304         node= ASTNodes.getNormalizedNode(node);
305         if (node.getLocationInParent() == ClassInstanceCreation.TYPE_PROPERTY) {
306             AnonymousClassDeclaration anon= ((ClassInstanceCreation)node.getParent()).getAnonymousClassDeclaration();
307             if (anon != null)
308                 return anon;
309         }
310         return (AnonymousClassDeclaration)ASTNodes.getParent(node, AnonymousClassDeclaration.class);
311     }
312
313     public RefactoringStatus validateInput() {
314         RefactoringStatus result= Checks.checkTypeName(fClassName);
315         if (result.hasFatalError())
316             return result;
317
318         if (fClassNamesUsed.contains(fClassName))
319             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_type_exists);
320         IMethodBinding superConstructorBinding = getSuperConstructorBinding();
321         if (superConstructorBinding == null)
322             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_compile_errors);
323         if (fClassName.equals(superConstructorBinding.getDeclaringClass().getName()))
324             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_another_name);
325         if (classNameHidesEnclosingType())
326             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_name_hides);
327         return result;
328     }
329
330     private boolean accessesAnonymousFields() {
331         List JavaDoc anonymousInnerFieldTypes = getAllEnclosingAnonymousTypesField();
332         List JavaDoc accessedField = getAllAccessedFields();
333         final Iterator JavaDoc it = anonymousInnerFieldTypes.iterator();
334         while(it.hasNext()) {
335             final IVariableBinding variableBinding = (IVariableBinding) it.next();
336             final Iterator JavaDoc it2 = accessedField.iterator();
337             while (it2.hasNext()) {
338                 IVariableBinding variableBinding2 = (IVariableBinding) it2.next();
339                 if(Bindings.equals(variableBinding, variableBinding2)) {
340                     return true;
341                 }
342             }
343         }
344         return false;
345     }
346
347     private List JavaDoc getAllAccessedFields() {
348         final List JavaDoc accessedFields= new ArrayList JavaDoc();
349
350         ASTVisitor visitor= new ASTVisitor() {
351
352             public boolean visit(FieldAccess node) {
353                 final IVariableBinding binding= node.resolveFieldBinding();
354                 if (binding != null && !binding.isEnumConstant())
355                     accessedFields.add(binding);
356                 return super.visit(node);
357             }
358
359             public boolean visit(QualifiedName node) {
360                 final IBinding binding= node.resolveBinding();
361                 if (binding != null && binding instanceof IVariableBinding) {
362                     IVariableBinding variable= (IVariableBinding) binding;
363                     if (!variable.isEnumConstant() && variable.isField())
364                         accessedFields.add(binding);
365                 }
366                 return super.visit(node);
367             }
368
369             public boolean visit(SimpleName node) {
370                 final IBinding binding= node.resolveBinding();
371                 if (binding != null && binding instanceof IVariableBinding) {
372                     IVariableBinding variable= (IVariableBinding) binding;
373                     if (!variable.isEnumConstant() && variable.isField())
374                         accessedFields.add(binding);
375                 }
376                 return super.visit(node);
377             }
378
379             public boolean visit(SuperFieldAccess node) {
380                 final IVariableBinding binding= node.resolveFieldBinding();
381                 if (binding != null && !binding.isEnumConstant())
382                     accessedFields.add(binding);
383                 return super.visit(node);
384             }
385         };
386         fAnonymousInnerClassNode.accept(visitor);
387
388         return accessedFields;
389     }
390
391     private List JavaDoc getAllEnclosingAnonymousTypesField() {
392         final List JavaDoc ans= new ArrayList JavaDoc();
393         final AbstractTypeDeclaration declaration= (AbstractTypeDeclaration) ASTNodes.getParent(fAnonymousInnerClassNode, AbstractTypeDeclaration.class);
394         AnonymousClassDeclaration anonymous= (AnonymousClassDeclaration) ASTNodes.getParent(fAnonymousInnerClassNode, ASTNode.ANONYMOUS_CLASS_DECLARATION);
395         while (anonymous != null) {
396             if (ASTNodes.isParent(anonymous, declaration)) {
397                 ITypeBinding binding= anonymous.resolveBinding();
398                 if (binding != null) {
399                     ans.addAll(Arrays.asList(binding.getDeclaredFields()));
400                 }
401             } else {
402                 break;
403             }
404             anonymous= (AnonymousClassDeclaration) ASTNodes.getParent(anonymous, ASTNode.ANONYMOUS_CLASS_DECLARATION);
405         }
406         return ans;
407     }
408
409     private boolean classNameHidesEnclosingType() {
410         ITypeBinding type= ((AbstractTypeDeclaration) ASTNodes.getParent(fAnonymousInnerClassNode, AbstractTypeDeclaration.class)).resolveBinding();
411         while (type != null) {
412             if (fClassName.equals(type.getName()))
413                 return true;
414             type= type.getDeclaringClass();
415         }
416         return false;
417     }
418
419     /*
420      * @see org.eclipse.jdt.internal.corext.refactoring.base.Refactoring#checkInput(org.eclipse.core.runtime.IProgressMonitor)
421      */

422     public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException {
423         try {
424             RefactoringStatus status= validateInput();
425             if (accessesAnonymousFields())
426                 status.merge(RefactoringStatus.createErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_anonymous_field_access));
427             return status;
428         } finally {
429             pm.done();
430         }
431     }
432     
433     public CompilationUnitChange createCompilationUnitChange(IProgressMonitor pm) throws CoreException {
434         final CompilationUnitRewrite rewrite= new CompilationUnitRewrite(fCu, fCompilationUnitNode);
435         final ITypeBinding[] typeParameters= getTypeParameters();
436         addNestedClass(rewrite, typeParameters);
437         modifyConstructorCall(rewrite, typeParameters);
438         return rewrite.createChange(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_name, false, pm);
439     }
440     
441
442     /*
443      * @see org.eclipse.jdt.internal.corext.refactoring.base.IRefactoring#createChange(org.eclipse.core.runtime.IProgressMonitor)
444      */

445     public Change createChange(IProgressMonitor pm) throws CoreException {
446         final CompilationUnitChange result= createCompilationUnitChange(pm);
447         result.setDescriptor(createRefactoringDescriptor());
448         return result;
449     }
450
451     private ITypeBinding[] getTypeParameters() {
452         final List JavaDoc parameters= new ArrayList JavaDoc(4);
453         final ClassInstanceCreation creation= (ClassInstanceCreation) fAnonymousInnerClassNode.getParent();
454         if (fDeclareStatic) {
455             final TypeVariableFinder finder= new TypeVariableFinder();
456             creation.accept(finder);
457             return finder.getResult();
458         } else {
459             final MethodDeclaration declaration= getEnclosingMethodDeclaration(creation);
460             if (declaration != null) {
461                 ITypeBinding binding= null;
462                 TypeParameter parameter= null;
463                 for (final Iterator JavaDoc iterator= declaration.typeParameters().iterator(); iterator.hasNext();) {
464                     parameter= (TypeParameter) iterator.next();
465                     binding= parameter.resolveBinding();
466                     if (binding != null)
467                         parameters.add(binding);
468                 }
469             }
470         }
471         final TypeVariableFinder finder= new TypeVariableFinder();
472         creation.accept(finder);
473         final ITypeBinding[] variables= finder.getResult();
474         final List JavaDoc remove= new ArrayList JavaDoc(4);
475         boolean match= false;
476         ITypeBinding binding= null;
477         ITypeBinding variable= null;
478         for (final Iterator JavaDoc iterator= parameters.iterator(); iterator.hasNext();) {
479             match= false;
480             binding= (ITypeBinding) iterator.next();
481             for (int index= 0; index < variables.length; index++) {
482                 variable= variables[index];
483                 if (variable.equals(binding))
484                     match= true;
485             }
486             if (!match)
487                 remove.add(binding);
488         }
489         parameters.removeAll(remove);
490         final ITypeBinding[] result= new ITypeBinding[parameters.size()];
491         parameters.toArray(result);
492         return result;
493     }
494
495     private MethodDeclaration getEnclosingMethodDeclaration(ASTNode node) {
496         ASTNode parent= node.getParent();
497         if (parent != null) {
498             if (parent instanceof AbstractTypeDeclaration)
499                 return null;
500             else if (parent instanceof MethodDeclaration)
501                 return (MethodDeclaration) parent;
502             return getEnclosingMethodDeclaration(parent);
503         }
504         return null;
505     }
506
507     private RefactoringChangeDescriptor createRefactoringDescriptor() {
508         final ITypeBinding binding= fAnonymousInnerClassNode.resolveBinding();
509         final String JavaDoc[] labels= new String JavaDoc[] { BindingLabelProvider.getBindingLabel(binding, JavaElementLabels.ALL_FULLY_QUALIFIED), BindingLabelProvider.getBindingLabel(binding.getDeclaringMethod(), JavaElementLabels.ALL_FULLY_QUALIFIED)};
510         final Map JavaDoc arguments= new HashMap JavaDoc();
511         final String JavaDoc projectName= fCu.getJavaProject().getElementName();
512         final int flags= RefactoringDescriptor.STRUCTURAL_CHANGE | JavaRefactoringDescriptor.JAR_REFACTORING | JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
513         final String JavaDoc description= RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_descriptor_description_short;
514         final String JavaDoc header= Messages.format(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_descriptor_description, labels);
515         final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(projectName, this, header);
516         comment.addSetting(Messages.format(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_original_pattern, BindingLabelProvider.getBindingLabel(binding, JavaElementLabels.ALL_FULLY_QUALIFIED)));
517         comment.addSetting(Messages.format(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_class_name_pattern, fClassName));
518         String JavaDoc visibility= JdtFlags.getVisibilityString(fVisibility);
519         if (visibility.length() == 0)
520             visibility= RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_default_visibility;
521         comment.addSetting(Messages.format(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_visibility_pattern, visibility));
522         if (fDeclareFinal && fDeclareStatic)
523             comment.addSetting(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_declare_final_static);
524         else if (fDeclareFinal)
525             comment.addSetting(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_declare_final);
526         else if (fDeclareStatic)
527             comment.addSetting(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_declare_static);
528         final JDTRefactoringDescriptor descriptor= new JDTRefactoringDescriptor(IJavaRefactorings.CONVERT_ANONYMOUS, projectName, description, comment.asString(), arguments, flags);
529         arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_INPUT, descriptor.elementToHandle(fCu));
530         arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_NAME, fClassName);
531         arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_SELECTION, new Integer JavaDoc(fSelectionStart).toString() + ' ' + new Integer JavaDoc(fSelectionLength).toString());
532         arguments.put(ATTRIBUTE_FINAL, Boolean.valueOf(fDeclareFinal).toString());
533         arguments.put(ATTRIBUTE_STATIC, Boolean.valueOf(fDeclareStatic).toString());
534         arguments.put(ATTRIBUTE_VISIBILITY, new Integer JavaDoc(fVisibility).toString());
535         return new RefactoringChangeDescriptor(descriptor);
536     }
537
538     private void modifyConstructorCall(CompilationUnitRewrite rewrite, ITypeBinding[] parameters) {
539         rewrite.getASTRewrite().replace(fAnonymousInnerClassNode.getParent(), createNewClassInstanceCreation(rewrite, parameters), null);
540     }
541
542     private ASTNode createNewClassInstanceCreation(CompilationUnitRewrite rewrite, ITypeBinding[] parameters) {
543         AST ast= fAnonymousInnerClassNode.getAST();
544         ClassInstanceCreation newClassCreation= ast.newClassInstanceCreation();
545         newClassCreation.setAnonymousClassDeclaration(null);
546         Type type= null;
547         SimpleName newNameNode= ast.newSimpleName(fClassName);
548         if (parameters.length > 0) {
549             final ParameterizedType parameterized= ast.newParameterizedType(ast.newSimpleType(newNameNode));
550             for (int index= 0; index < parameters.length; index++)
551                 parameterized.typeArguments().add(ast.newSimpleType(ast.newSimpleName(parameters[index].getName())));
552             type= parameterized;
553         } else
554             type= ast.newSimpleType(newNameNode);
555         newClassCreation.setType(type);
556         copyArguments(rewrite, newClassCreation);
557         addArgumentsForLocalsUsedInInnerClass(rewrite, newClassCreation);
558         
559         addLinkedPosition(KEY_TYPE_NAME, newNameNode, rewrite.getASTRewrite(), true);
560
561         return newClassCreation;
562     }
563
564     private void addArgumentsForLocalsUsedInInnerClass(CompilationUnitRewrite rewrite, ClassInstanceCreation newClassCreation) {
565         IVariableBinding[] usedLocals= getUsedLocalVariables();
566         for (int i= 0; i < usedLocals.length; i++) {
567             final AST ast= fAnonymousInnerClassNode.getAST();
568             final IVariableBinding binding= usedLocals[i];
569             Name name= null;
570             if (binding.isEnumConstant())
571                 name= ast.newQualifiedName(ast.newSimpleName(binding.getDeclaringClass().getName()), ast.newSimpleName(binding.getName()));
572             else
573                 name= ast.newSimpleName(binding.getName());
574             newClassCreation.arguments().add(name);
575         }
576     }
577
578     private void copyArguments(CompilationUnitRewrite rewrite, ClassInstanceCreation newClassCreation) {
579         for (Iterator JavaDoc iter= ((ClassInstanceCreation) fAnonymousInnerClassNode.getParent()).arguments().iterator(); iter.hasNext(); )
580             newClassCreation.arguments().add(rewrite.getASTRewrite().createCopyTarget((Expression)iter.next()));
581     }
582
583     private void addNestedClass(CompilationUnitRewrite rewrite, ITypeBinding[] typeParameters) throws CoreException {
584         final AbstractTypeDeclaration declarations= (AbstractTypeDeclaration) ASTNodes.getParent(fAnonymousInnerClassNode, AbstractTypeDeclaration.class);
585         int index= findIndexOfFistNestedClass(declarations.bodyDeclarations());
586         if (index == -1)
587             index= 0;
588         rewrite.getASTRewrite().getListRewrite(declarations, declarations.getBodyDeclarationsProperty()).insertAt(createNewNestedClass(rewrite, typeParameters), index, null);
589     }
590
591     private static int findIndexOfFistNestedClass(List JavaDoc bodyDeclarations) {
592         for (int i= 0, n= bodyDeclarations.size(); i < n; i++) {
593             BodyDeclaration each= (BodyDeclaration)bodyDeclarations.get(i);
594             if (isNestedType(each))
595                 return i;
596         }
597         return -1;
598     }
599
600     private static boolean isNestedType(BodyDeclaration each) {
601         if (!(each instanceof AbstractTypeDeclaration))
602             return false;
603         return (each.getParent() instanceof AbstractTypeDeclaration);
604     }
605
606     private AbstractTypeDeclaration createNewNestedClass(CompilationUnitRewrite rewrite, ITypeBinding[] typeParameters) throws CoreException {
607         final AST ast= fAnonymousInnerClassNode.getAST();
608         
609         final TypeDeclaration newDeclaration= ast.newTypeDeclaration();
610         newDeclaration.setInterface(false);
611         newDeclaration.setJavadoc(null);
612         newDeclaration.modifiers().addAll(ASTNodeFactory.newModifiers(ast, createModifiersForNestedClass()));
613         newDeclaration.setName(ast.newSimpleName(fClassName));
614         
615         TypeParameter parameter= null;
616         for (int index= 0; index < typeParameters.length; index++) {
617             parameter= ast.newTypeParameter();
618             parameter.setName(ast.newSimpleName(typeParameters[index].getName()));
619             newDeclaration.typeParameters().add(parameter);
620         }
621         setSuperType(newDeclaration);
622         
623         IJavaProject project= fCu.getJavaProject();
624         
625         IVariableBinding[] bindings= getUsedLocalVariables();
626         ArrayList JavaDoc fieldNames= new ArrayList JavaDoc();
627         for (int i= 0; i < bindings.length; i++) {
628             String JavaDoc name= StubUtility.removePrefixAndSuffixForVariable(project, bindings[i]);
629             String JavaDoc[] fieldNameProposals= StubUtility.getVariableNameSuggestions(StubUtility.INSTANCE_FIELD, project, name, 0, fieldNames, true);
630             fieldNames.add(fieldNameProposals[0]);
631             
632             
633             if (fLinkedProposalModel != null) {
634                 LinkedProposalPositionGroup positionGroup= fLinkedProposalModel.getPositionGroup(KEY_FIELD_NAME_EXT + i, true);
635                 for (int k= 0; k < fieldNameProposals.length; k++) {
636                     positionGroup.addProposal(fieldNameProposals[k], null, fieldNameProposals.length - k);
637                 }
638             }
639         }
640         String JavaDoc[] allFieldNames= (String JavaDoc[]) fieldNames.toArray(new String JavaDoc[fieldNames.size()]);
641         
642         List JavaDoc newBodyDeclarations= newDeclaration.bodyDeclarations();
643         
644         createFieldsForAccessedLocals(rewrite, bindings, allFieldNames, newBodyDeclarations);
645         
646         MethodDeclaration newConstructorDecl= createNewConstructor(rewrite, bindings, allFieldNames);
647         if (newConstructorDecl != null) {
648             newBodyDeclarations.add(newConstructorDecl);
649         }
650         
651         updateAndMoveBodyDeclarations(rewrite, bindings, allFieldNames, newBodyDeclarations, newConstructorDecl);
652         
653         if (doAddComments()) {
654             String JavaDoc[] parameterNames= new String JavaDoc[typeParameters.length];
655             for (int index= 0; index < parameterNames.length; index++) {
656                 parameterNames[index]= typeParameters[index].getName();
657             }
658             String JavaDoc string= CodeGeneration.getTypeComment(rewrite.getCu(), fClassName, parameterNames, StubUtility.getLineDelimiterUsed(fCu));
659             if (string != null) {
660                 Javadoc javadoc= (Javadoc) rewrite.getASTRewrite().createStringPlaceholder(string, ASTNode.JAVADOC);
661                 newDeclaration.setJavadoc(javadoc);
662             }
663         }
664         if (fLinkedProposalModel != null) {
665             addLinkedPosition(KEY_TYPE_NAME, newDeclaration.getName(), rewrite.getASTRewrite(), false);
666             ModifierCorrectionSubProcessor.installLinkedVisibilityProposals(fLinkedProposalModel, rewrite.getASTRewrite(), newDeclaration.modifiers(), false);
667         }
668         
669         return newDeclaration;
670     }
671
672     private void updateAndMoveBodyDeclarations(CompilationUnitRewrite rewriter, IVariableBinding[] bindings, String JavaDoc[] fieldNames, List JavaDoc newBodyDeclarations, MethodDeclaration newConstructorDecl) throws JavaModelException {
673         final ASTRewrite astRewrite= rewriter.getASTRewrite();
674         final AST ast= astRewrite.getAST();
675         
676         final boolean useThisAccess= useThisForFieldAccess();
677         
678         int fieldInsertIndex= newConstructorDecl != null ? newBodyDeclarations.lastIndexOf(newConstructorDecl) : newBodyDeclarations.size();
679         
680         for (Iterator JavaDoc iterator= fAnonymousInnerClassNode.bodyDeclarations().iterator(); iterator.hasNext();) {
681             BodyDeclaration body= (BodyDeclaration) iterator.next();
682             
683             for (int i= 0; i < bindings.length; i++) {
684                 SimpleName[] names= LinkedNodeFinder.findByBinding(body, bindings[i]);
685                 String JavaDoc fieldName= fieldNames[i];
686                 for (int k= 0; k < names.length; k++) {
687                     SimpleName newNode= ast.newSimpleName(fieldName);
688                     if (useThisAccess) {
689                         FieldAccess access= ast.newFieldAccess();
690                         access.setExpression(ast.newThisExpression());
691                         access.setName(newNode);
692                         astRewrite.replace(names[k], access, null);
693                     } else {
694                         astRewrite.replace(names[k], newNode, null);
695                     }
696                     addLinkedPosition(KEY_FIELD_NAME_EXT + i, newNode, astRewrite, false);
697                 }
698             }
699             if (body instanceof Initializer || body instanceof FieldDeclaration) {
700                 newBodyDeclarations.add(fieldInsertIndex++, astRewrite.createMoveTarget(body));
701             } else {
702                 newBodyDeclarations.add(astRewrite.createMoveTarget(body));
703             }
704         }
705         
706         if (newConstructorDecl != null) {
707             // move initialization of existing fields to constructor if an outer is referenced
708
List JavaDoc bodyStatements= newConstructorDecl.getBody().statements();
709
710             List JavaDoc fieldsToInitializeInConstructor= getFieldsToInitializeInConstructor();
711             for (Iterator JavaDoc iter= fieldsToInitializeInConstructor.iterator(); iter.hasNext();) {
712                 VariableDeclarationFragment fragment= (VariableDeclarationFragment) iter.next();
713                 Expression initializer= fragment.getInitializer();
714                 Expression replacement= (Expression) astRewrite.get(fragment, VariableDeclarationFragment.INITIALIZER_PROPERTY);
715                 if (replacement == initializer) {
716                     replacement= (Expression) astRewrite.createMoveTarget(initializer);
717                 }
718                 astRewrite.remove(initializer, null);
719                 SimpleName fieldNameNode= ast.newSimpleName(fragment.getName().getIdentifier());
720                 bodyStatements.add(newFieldAssignment(ast, fieldNameNode, replacement, useThisAccess));
721             }
722         }
723     }
724
725     private void createFieldsForAccessedLocals(CompilationUnitRewrite rewrite, IVariableBinding[] varBindings, String JavaDoc[] fieldNames, List JavaDoc newBodyDeclarations) {
726         final ImportRewrite importRewrite= rewrite.getImportRewrite();
727         final ASTRewrite astRewrite= rewrite.getASTRewrite();
728         final AST ast= astRewrite.getAST();
729                 
730         for (int i= 0; i < varBindings.length; i++) {
731             VariableDeclarationFragment fragment= ast.newVariableDeclarationFragment();
732             fragment.setExtraDimensions(0);
733             fragment.setInitializer(null);
734             fragment.setName(ast.newSimpleName(fieldNames[i]));
735             FieldDeclaration field= ast.newFieldDeclaration(fragment);
736             ITypeBinding varType= varBindings[i].getType();
737             field.setType(importRewrite.addImport(varType, ast));
738             field.modifiers().addAll(ASTNodeFactory.newModifiers(ast, Modifier.PRIVATE | Modifier.FINAL));
739             if (doAddComments()) {
740                 try {
741                     String JavaDoc string= CodeGeneration.getFieldComment(rewrite.getCu(), varType.getName(), fieldNames[i], StubUtility.getLineDelimiterUsed(fCu));
742                     if (string != null) {
743                         Javadoc javadoc= (Javadoc) astRewrite.createStringPlaceholder(string, ASTNode.JAVADOC);
744                         field.setJavadoc(javadoc);
745                     }
746                 } catch (CoreException exception) {
747                     JavaPlugin.log(exception);
748                 }
749             }
750             
751             newBodyDeclarations.add(field);
752             
753             addLinkedPosition(KEY_FIELD_NAME_EXT + i, fragment.getName(), astRewrite, false);
754         }
755     }
756     
757     private void addLinkedPosition(String JavaDoc key, ASTNode nodeToTrack, ASTRewrite rewrite, boolean isFirst) {
758         if (fLinkedProposalModel != null) {
759             fLinkedProposalModel.getPositionGroup(key, true).addPosition(rewrite.track(nodeToTrack), isFirst);
760         }
761     }
762     
763
764     private IVariableBinding[] getUsedLocalVariables() {
765         final Set JavaDoc result= new HashSet JavaDoc(0);
766         collectRefrencedVariables(fAnonymousInnerClassNode, result);
767         ArrayList JavaDoc usedLocals= new ArrayList JavaDoc();
768         for (Iterator JavaDoc iterator= result.iterator(); iterator.hasNext();) {
769             IVariableBinding next= (IVariableBinding) iterator.next();
770             if (isBindingToTemp(next)) {
771                 usedLocals.add(next);
772             }
773         }
774         return (IVariableBinding[])usedLocals.toArray(new IVariableBinding[usedLocals.size()]);
775     }
776
777     private void collectRefrencedVariables(ASTNode root, final Set JavaDoc result) {
778         root.accept(new ASTVisitor() {
779             public boolean visit(SimpleName node) {
780                 IBinding binding= node.resolveBinding();
781                 if (binding instanceof IVariableBinding)
782                     result.add(binding);
783                 return true;
784             }
785         });
786     }
787
788     private boolean isBindingToTemp(IVariableBinding variable) {
789         if (variable.isField())
790             return false;
791         if (!Modifier.isFinal(variable.getModifiers()))
792             return false;
793         ASTNode declaringNode= fCompilationUnitNode.findDeclaringNode(variable);
794         if (declaringNode == null)
795             return false;
796         if (ASTNodes.isParent(declaringNode, fAnonymousInnerClassNode))
797             return false;
798         return true;
799     }
800
801     private MethodDeclaration createNewConstructor(CompilationUnitRewrite rewrite, IVariableBinding[] bindings, String JavaDoc[] fieldNames) throws JavaModelException {
802         ClassInstanceCreation instanceCreation= (ClassInstanceCreation) fAnonymousInnerClassNode.getParent();
803         
804         if (instanceCreation.arguments().isEmpty() && bindings.length == 0)
805             return null;
806
807         IJavaProject project= fCu.getJavaProject();
808         AST ast= rewrite.getAST();
809         ImportRewrite importRewrite= rewrite.getImportRewrite();
810         ASTRewrite astRewrite= rewrite.getASTRewrite();
811         
812         MethodDeclaration newConstructor= ast.newMethodDeclaration();
813         newConstructor.setConstructor(true);
814         newConstructor.setExtraDimensions(0);
815         newConstructor.setJavadoc(null);
816         newConstructor.modifiers().addAll(ASTNodeFactory.newModifiers(ast, fVisibility));
817         newConstructor.setName(ast.newSimpleName(fClassName));
818         addLinkedPosition(KEY_TYPE_NAME, newConstructor.getName(), astRewrite, false);
819         
820         newConstructor.setBody(ast.newBlock());
821         
822         List JavaDoc newStatements= newConstructor.getBody().statements();
823         
824         List JavaDoc newParameters= newConstructor.parameters();
825         List JavaDoc newParameterNames= new ArrayList JavaDoc();
826         
827         // add parameters for elements passed with the instance creation
828
if (!instanceCreation.arguments().isEmpty()) {
829             IMethodBinding constructorBinding= getSuperConstructorBinding();
830             if (constructorBinding != null) {
831                 SuperConstructorInvocation superConstructorInvocation= ast.newSuperConstructorInvocation();
832                 ITypeBinding[] parameterTypes= constructorBinding.getParameterTypes();
833                 String JavaDoc[][] parameterNames= StubUtility.suggestArgumentNamesWithProposals(project, constructorBinding);
834                 for (int i= 0; i < parameterNames.length; i++) {
835                     String JavaDoc[] nameProposals= parameterNames[i];
836                     String JavaDoc paramName= nameProposals[0];
837                     
838                     SingleVariableDeclaration param= newParameterDeclaration(ast, importRewrite, paramName, parameterTypes[i]);
839                     newParameters.add(param);
840                     newParameterNames.add(paramName);
841                     
842                     SimpleName newSIArgument= ast.newSimpleName(paramName);
843                     superConstructorInvocation.arguments().add(newSIArgument);
844                     
845                     if (fLinkedProposalModel != null) {
846                         LinkedProposalPositionGroup positionGroup= fLinkedProposalModel.getPositionGroup(KEY_PARAM_NAME_CONST+ String.valueOf(i), true);
847                         positionGroup.addPosition(astRewrite.track(param.getName()), false);
848                         positionGroup.addPosition(astRewrite.track(newSIArgument), false);
849                         for (int k= 0; k < nameProposals.length; k++) {
850                             positionGroup.addProposal(nameProposals[k], null, nameProposals.length - k);
851                         }
852                     }
853                 }
854                 newStatements.add(superConstructorInvocation);
855             }
856         }
857         // add parameters for all outer variables used
858
boolean useThisAccess= useThisForFieldAccess();
859         for (int i= 0; i < bindings.length; i++) {
860             String JavaDoc baseName= StubUtility.removePrefixAndSuffixForVariable(project, bindings[i]);
861             String JavaDoc[] paramNameProposals= StubUtility.getVariableNameSuggestions(StubUtility.PARAMETER, project, baseName, 0, newParameterNames, true);
862             String JavaDoc paramName= paramNameProposals[0];
863             
864             SingleVariableDeclaration param= newParameterDeclaration(ast, importRewrite, paramName, bindings[i].getType());
865             newParameters.add(param);
866             newParameterNames.add(paramName);
867             
868             String JavaDoc fieldName= fieldNames[i];
869             SimpleName fieldNameNode= ast.newSimpleName(fieldName);
870             SimpleName paramNameNode= ast.newSimpleName(paramName);
871             newStatements.add(newFieldAssignment(ast, fieldNameNode, paramNameNode, useThisAccess || newParameterNames.contains(fieldName)));
872             
873             if (fLinkedProposalModel != null) {
874                 LinkedProposalPositionGroup positionGroup= fLinkedProposalModel.getPositionGroup(KEY_PARAM_NAME_EXT+ String.valueOf(i), true);
875                 positionGroup.addPosition(astRewrite.track(param.getName()), false);
876                 positionGroup.addPosition(astRewrite.track(paramNameNode), false);
877                 for (int k= 0; k < paramNameProposals.length; k++) {
878                     positionGroup.addProposal(paramNameProposals[k], null, paramNameProposals.length - k);
879                 }
880                 
881                 fLinkedProposalModel.getPositionGroup(KEY_FIELD_NAME_EXT + i, true).addPosition(astRewrite.track(fieldNameNode), false);
882             }
883         }
884
885         addExceptionsToNewConstructor(newConstructor);
886         
887         if (doAddComments()) {
888             try {
889                 String JavaDoc[] allParamNames= (String JavaDoc[]) newParameterNames.toArray(new String JavaDoc[newParameterNames.size()]);
890                 String JavaDoc string= CodeGeneration.getMethodComment(fCu, fClassName, fClassName, allParamNames, new String JavaDoc[0], null, new String JavaDoc[0], null, StubUtility.getLineDelimiterUsed(fCu));
891                 if (string != null) {
892                     Javadoc javadoc= (Javadoc) astRewrite.createStringPlaceholder(string, ASTNode.JAVADOC);
893                     newConstructor.setJavadoc(javadoc);
894                 }
895             } catch (CoreException exception) {
896                 JavaPlugin.log(exception);
897             }
898         }
899         return newConstructor;
900     }
901     
902     private Statement newFieldAssignment(AST ast, SimpleName fieldNameNode, Expression initializer, boolean useThisAccess) {
903         Assignment assignment= ast.newAssignment();
904         if (useThisAccess) {
905             FieldAccess access= ast.newFieldAccess();
906             access.setExpression(ast.newThisExpression());
907             access.setName(fieldNameNode);
908             assignment.setLeftHandSide(access);
909         } else {
910             assignment.setLeftHandSide(fieldNameNode);
911         }
912         assignment.setOperator(Assignment.Operator.ASSIGN);
913         assignment.setRightHandSide(initializer);
914         
915         return ast.newExpressionStatement(assignment);
916      }
917     
918
919     // live List of VariableDeclarationFragments
920
private List JavaDoc getFieldsToInitializeInConstructor() {
921         List JavaDoc result= new ArrayList JavaDoc(0);
922         for (Iterator JavaDoc iter= fAnonymousInnerClassNode.bodyDeclarations().iterator(); iter.hasNext(); ) {
923             Object JavaDoc element= iter.next();
924             if (element instanceof FieldDeclaration) {
925                 List JavaDoc fragments= ((FieldDeclaration) element).fragments();
926                 for (Iterator JavaDoc fragmentIter= fragments.iterator(); fragmentIter.hasNext(); ) {
927                     VariableDeclarationFragment fragment= (VariableDeclarationFragment) fragmentIter.next();
928                     if (isToBeInitializerInConstructor(fragment, result))
929                         result.add(fragment);
930                 }
931             }
932         }
933         return result;
934     }
935
936     private boolean isToBeInitializerInConstructor(VariableDeclarationFragment fragment, List JavaDoc fieldsToInitialize) {
937         return fragment.getInitializer() != null && areLocalsUsedIn(fragment.getInitializer(), fieldsToInitialize);
938     }
939
940     private boolean areLocalsUsedIn(Expression fieldInitializer, List JavaDoc fieldsToInitialize) {
941         Set JavaDoc localsUsed= new HashSet JavaDoc(0);
942         collectRefrencedVariables(fieldInitializer, localsUsed);
943         
944         ITypeBinding anonType= fAnonymousInnerClassNode.resolveBinding();
945         
946         for (Iterator JavaDoc iterator= localsUsed.iterator(); iterator.hasNext();) {
947             IVariableBinding curr= (IVariableBinding) iterator.next();
948             if (isBindingToTemp(curr)) { // reference a local from outside
949
return true;
950             } else if (curr.isField() && (curr.getDeclaringClass() == anonType) && fieldsToInitialize.contains(fCompilationUnitNode.findDeclaringNode(curr))) {
951                 return true; // references a field that references a local from outside
952
}
953         }
954         return false;
955     }
956
957     private IMethodBinding getSuperConstructorBinding() {
958         //workaround for missing java core functionality - finding a
959
// super constructor for an anonymous class creation
960
IMethodBinding anonConstr= ((ClassInstanceCreation) fAnonymousInnerClassNode.getParent()).resolveConstructorBinding();
961         if (anonConstr == null)
962             return null;
963         ITypeBinding superClass= anonConstr.getDeclaringClass().getSuperclass();
964         IMethodBinding[] superMethods= superClass.getDeclaredMethods();
965         for (int i= 0; i < superMethods.length; i++) {
966             IMethodBinding superMethod= superMethods[i];
967             if (superMethod.isConstructor() && parameterTypesMatch(superMethod, anonConstr))
968                 return superMethod;
969         }
970         Assert.isTrue(false);//there's no way - it must be there
971
return null;
972     }
973
974     private static boolean parameterTypesMatch(IMethodBinding m1, IMethodBinding m2) {
975         ITypeBinding[] m1Params= m1.getParameterTypes();
976         ITypeBinding[] m2Params= m2.getParameterTypes();
977         if (m1Params.length != m2Params.length)
978             return false;
979         for (int i= 0; i < m2Params.length; i++) {
980             if (!m1Params[i].equals(m2Params[i]))
981                 return false;
982         }
983         return true;
984     }
985
986     private void addExceptionsToNewConstructor(MethodDeclaration newConstructor) {
987         IMethodBinding constructorBinding= getSuperConstructorBinding();
988         if (constructorBinding == null)
989             return;
990         ITypeBinding[] exceptions= constructorBinding.getExceptionTypes();
991         for (int i= 0; i < exceptions.length; i++) {
992             Name exceptionTypeName= fAnonymousInnerClassNode.getAST().newName(Bindings.getNameComponents(exceptions[i]));
993             newConstructor.thrownExceptions().add(exceptionTypeName);
994         }
995     }
996
997     private SingleVariableDeclaration newParameterDeclaration(AST ast, ImportRewrite importRewrite, String JavaDoc paramName, ITypeBinding paramType) {
998         SingleVariableDeclaration param= ast.newSingleVariableDeclaration();
999         param.setExtraDimensions(0);
1000        param.setInitializer(null);
1001        param.setType(importRewrite.addImport(paramType, ast));
1002        param.setName(ast.newSimpleName(paramName));
1003        return param;
1004    }
1005
1006    private void setSuperType(TypeDeclaration declaration) throws JavaModelException {
1007        ClassInstanceCreation classInstanceCreation= (ClassInstanceCreation) fAnonymousInnerClassNode.getParent();
1008        ITypeBinding binding= classInstanceCreation.resolveTypeBinding();
1009        if (binding == null)
1010            return;
1011        Type newType= (Type) ASTNode.copySubtree(fAnonymousInnerClassNode.getAST(), classInstanceCreation.getType());
1012        if (binding.getSuperclass().getQualifiedName().equals("java.lang.Object")) { //$NON-NLS-1$
1013
Assert.isTrue(binding.getInterfaces().length <= 1);
1014            if (binding.getInterfaces().length == 0)
1015                return;
1016            declaration.superInterfaceTypes().add(0, newType);
1017        } else {
1018            declaration.setSuperclassType(newType);
1019        }
1020    }
1021
1022    private ITypeBinding getSuperTypeBinding() {
1023        ITypeBinding types= fAnonymousInnerClassNode.resolveBinding();
1024        ITypeBinding[] interfaces= types.getInterfaces();
1025        if (interfaces.length > 0)
1026            return interfaces[0];
1027        else
1028            return types.getSuperclass();
1029    }
1030
1031    private int createModifiersForNestedClass() {
1032        int flags= fVisibility;
1033        if (fDeclareFinal)
1034            flags|= Modifier.FINAL;
1035        if (mustInnerClassBeStatic() || fDeclareStatic)
1036            flags|= Modifier.STATIC;
1037        return flags;
1038    }
1039
1040    public boolean mustInnerClassBeStatic() {
1041        ITypeBinding typeBinding = ((AbstractTypeDeclaration) ASTNodes.getParent(fAnonymousInnerClassNode, AbstractTypeDeclaration.class)).resolveBinding();
1042        ASTNode current = fAnonymousInnerClassNode.getParent();
1043        boolean ans = false;
1044        while(current != null) {
1045            switch(current.getNodeType()) {
1046                case ASTNode.ANONYMOUS_CLASS_DECLARATION:
1047                {
1048                    AnonymousClassDeclaration enclosingAnonymousClassDeclaration= (AnonymousClassDeclaration)current;
1049                    ITypeBinding binding= enclosingAnonymousClassDeclaration.resolveBinding();
1050                    if (binding != null && Bindings.isSuperType(typeBinding, binding.getSuperclass())) {
1051                        return false;
1052                    }
1053                    break;
1054                }
1055                case ASTNode.FIELD_DECLARATION:
1056                {
1057                    FieldDeclaration enclosingFieldDeclaration= (FieldDeclaration)current;
1058                    if (Modifier.isStatic(enclosingFieldDeclaration.getModifiers())) {
1059                        ans = true;
1060                    }
1061                    break;
1062                }
1063                case ASTNode.METHOD_DECLARATION:
1064                {
1065                    MethodDeclaration enclosingMethodDeclaration = (MethodDeclaration)current;
1066                    if (Modifier.isStatic(enclosingMethodDeclaration.getModifiers())) {
1067                        ans = true;
1068                    }
1069                    break;
1070                }
1071                case ASTNode.TYPE_DECLARATION:
1072                {
1073                    return ans;
1074                }
1075            }
1076            current = current.getParent();
1077        }
1078        return ans;
1079    }
1080
1081    public RefactoringStatus initialize(final RefactoringArguments arguments) {
1082        fSelfInitializing= true;
1083        if (arguments instanceof JavaRefactoringArguments) {
1084            final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments;
1085            final String JavaDoc handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT);
1086            if (handle != null) {
1087                final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false);
1088                if (element == null || !element.exists() || element.getElementType() != IJavaElement.COMPILATION_UNIT)
1089                    return createInputFatalStatus(element, IJavaRefactorings.CONVERT_ANONYMOUS);
1090                else {
1091                    fCu= (ICompilationUnit) element;
1092                }
1093            } else
1094                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT));
1095            final String JavaDoc name= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_NAME);
1096            if (name != null && !"".equals(name)) //$NON-NLS-1$
1097
fClassName= name;
1098            else
1099                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_NAME));
1100            final String JavaDoc visibility= extended.getAttribute(ATTRIBUTE_VISIBILITY);
1101            if (visibility != null && !"".equals(visibility)) {//$NON-NLS-1$
1102
int flag= 0;
1103                try {
1104                    flag= Integer.parseInt(visibility);
1105                } catch (NumberFormatException JavaDoc exception) {
1106                    return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_VISIBILITY));
1107                }
1108                fVisibility= flag;
1109            }
1110            final String JavaDoc selection= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_SELECTION);
1111            if (selection != null) {
1112                int offset= -1;
1113                int length= -1;
1114                final StringTokenizer JavaDoc tokenizer= new StringTokenizer JavaDoc(selection);
1115                if (tokenizer.hasMoreTokens())
1116                    offset= Integer.valueOf(tokenizer.nextToken()).intValue();
1117                if (tokenizer.hasMoreTokens())
1118                    length= Integer.valueOf(tokenizer.nextToken()).intValue();
1119                if (offset >= 0 && length >= 0) {
1120                    fSelectionStart= offset;
1121                    fSelectionLength= length;
1122                } else
1123                    return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new Object JavaDoc[] { selection, JDTRefactoringDescriptor.ATTRIBUTE_SELECTION}));
1124            } else
1125                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_SELECTION));
1126            final String JavaDoc declareStatic= extended.getAttribute(ATTRIBUTE_STATIC);
1127            if (declareStatic != null) {
1128                fDeclareStatic= Boolean.valueOf(declareStatic).booleanValue();
1129            } else
1130                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_STATIC));
1131            final String JavaDoc declareFinal= extended.getAttribute(ATTRIBUTE_FINAL);
1132            if (declareFinal != null) {
1133                fDeclareFinal= Boolean.valueOf(declareStatic).booleanValue();
1134            } else
1135                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_FINAL));
1136        } else
1137            return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
1138        return new RefactoringStatus();
1139    }
1140}
1141
Popular Tags