1 16 package org.eclipse.jdt.internal.corext.refactoring.code; 17 18 import java.util.ArrayList ; 19 import java.util.Arrays ; 20 import java.util.Collections ; 21 import java.util.HashMap ; 22 import java.util.HashSet ; 23 import java.util.Iterator ; 24 import java.util.List ; 25 import java.util.Map ; 26 import java.util.Set ; 27 import java.util.StringTokenizer ; 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 ATTRIBUTE_VISIBILITY= "visibility"; private static final String ATTRIBUTE_FINAL= "final"; private static final String ATTRIBUTE_STATIC= "static"; 113 private static final String KEY_TYPE_NAME= "type_name"; private static final String KEY_PARAM_NAME_EXT= "param_name_ext"; private static final String KEY_PARAM_NAME_CONST= "param_name_const"; private static final String KEY_FIELD_NAME_EXT= "field_name_ext"; 118 public static class TypeVariableFinder extends ASTVisitor { 119 120 private final Map fBindings= new HashMap (); 121 private final List fFound= new ArrayList (); 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; 145 private boolean fDeclareFinal= true; 146 private boolean fDeclareStatic; 147 private String fClassName= ""; 149 private CompilationUnit fCompilationUnitNode; 150 private AnonymousClassDeclaration fAnonymousInnerClassNode; 151 private Set fClassNamesUsed; 152 private boolean fSelfInitializing= false; 153 154 private LinkedProposalModel fLinkedProposalModel; 155 156 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 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 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 (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 anonymousInnerFieldTypes = getAllEnclosingAnonymousTypesField(); 332 List accessedField = getAllAccessedFields(); 333 final Iterator it = anonymousInnerFieldTypes.iterator(); 334 while(it.hasNext()) { 335 final IVariableBinding variableBinding = (IVariableBinding) it.next(); 336 final Iterator 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 getAllAccessedFields() { 348 final List accessedFields= new ArrayList (); 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 getAllEnclosingAnonymousTypesField() { 392 final List ans= new ArrayList (); 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 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 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 parameters= new ArrayList (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 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 remove= new ArrayList (4); 475 boolean match= false; 476 ITypeBinding binding= null; 477 ITypeBinding variable= null; 478 for (final Iterator 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 [] labels= new String [] { BindingLabelProvider.getBindingLabel(binding, JavaElementLabels.ALL_FULLY_QUALIFIED), BindingLabelProvider.getBindingLabel(binding.getDeclaringMethod(), JavaElementLabels.ALL_FULLY_QUALIFIED)}; 510 final Map arguments= new HashMap (); 511 final String projectName= fCu.getJavaProject().getElementName(); 512 final int flags= RefactoringDescriptor.STRUCTURAL_CHANGE | JavaRefactoringDescriptor.JAR_REFACTORING | JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT; 513 final String description= RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_descriptor_description_short; 514 final String 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 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 (fSelectionStart).toString() + ' ' + new Integer (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 (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 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 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 fieldNames= new ArrayList (); 627 for (int i= 0; i < bindings.length; i++) { 628 String name= StubUtility.removePrefixAndSuffixForVariable(project, bindings[i]); 629 String [] 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 [] allFieldNames= (String []) fieldNames.toArray(new String [fieldNames.size()]); 641 642 List 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 [] parameterNames= new String [typeParameters.length]; 655 for (int index= 0; index < parameterNames.length; index++) { 656 parameterNames[index]= typeParameters[index].getName(); 657 } 658 String 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 [] fieldNames, List 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 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 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 List bodyStatements= newConstructorDecl.getBody().statements(); 709 710 List fieldsToInitializeInConstructor= getFieldsToInitializeInConstructor(); 711 for (Iterator 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 [] fieldNames, List 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 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 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 result= new HashSet (0); 766 collectRefrencedVariables(fAnonymousInnerClassNode, result); 767 ArrayList usedLocals= new ArrayList (); 768 for (Iterator 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 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 [] 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 newStatements= newConstructor.getBody().statements(); 823 824 List newParameters= newConstructor.parameters(); 825 List newParameterNames= new ArrayList (); 826 827 if (!instanceCreation.arguments().isEmpty()) { 829 IMethodBinding constructorBinding= getSuperConstructorBinding(); 830 if (constructorBinding != null) { 831 SuperConstructorInvocation superConstructorInvocation= ast.newSuperConstructorInvocation(); 832 ITypeBinding[] parameterTypes= constructorBinding.getParameterTypes(); 833 String [][] parameterNames= StubUtility.suggestArgumentNamesWithProposals(project, constructorBinding); 834 for (int i= 0; i < parameterNames.length; i++) { 835 String [] nameProposals= parameterNames[i]; 836 String 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 boolean useThisAccess= useThisForFieldAccess(); 859 for (int i= 0; i < bindings.length; i++) { 860 String baseName= StubUtility.removePrefixAndSuffixForVariable(project, bindings[i]); 861 String [] paramNameProposals= StubUtility.getVariableNameSuggestions(StubUtility.PARAMETER, project, baseName, 0, newParameterNames, true); 862 String 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 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 [] allParamNames= (String []) newParameterNames.toArray(new String [newParameterNames.size()]); 890 String string= CodeGeneration.getMethodComment(fCu, fClassName, fClassName, allParamNames, new String [0], null, new String [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 private List getFieldsToInitializeInConstructor() { 921 List result= new ArrayList (0); 922 for (Iterator iter= fAnonymousInnerClassNode.bodyDeclarations().iterator(); iter.hasNext(); ) { 923 Object element= iter.next(); 924 if (element instanceof FieldDeclaration) { 925 List fragments= ((FieldDeclaration) element).fragments(); 926 for (Iterator 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 fieldsToInitialize) { 937 return fragment.getInitializer() != null && areLocalsUsedIn(fragment.getInitializer(), fieldsToInitialize); 938 } 939 940 private boolean areLocalsUsedIn(Expression fieldInitializer, List fieldsToInitialize) { 941 Set localsUsed= new HashSet (0); 942 collectRefrencedVariables(fieldInitializer, localsUsed); 943 944 ITypeBinding anonType= fAnonymousInnerClassNode.resolveBinding(); 945 946 for (Iterator iterator= localsUsed.iterator(); iterator.hasNext();) { 947 IVariableBinding curr= (IVariableBinding) iterator.next(); 948 if (isBindingToTemp(curr)) { return true; 950 } else if (curr.isField() && (curr.getDeclaringClass() == anonType) && fieldsToInitialize.contains(fCompilationUnitNode.findDeclaringNode(curr))) { 951 return true; } 953 } 954 return false; 955 } 956 957 private IMethodBinding getSuperConstructorBinding() { 958 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); 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 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")) { 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 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 name= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_NAME); 1096 if (name != null && !"".equals(name)) fClassName= name; 1098 else 1099 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_NAME)); 1100 final String visibility= extended.getAttribute(ATTRIBUTE_VISIBILITY); 1101 if (visibility != null && !"".equals(visibility)) { int flag= 0; 1103 try { 1104 flag= Integer.parseInt(visibility); 1105 } catch (NumberFormatException exception) { 1106 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_VISIBILITY)); 1107 } 1108 fVisibility= flag; 1109 } 1110 final String selection= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_SELECTION); 1111 if (selection != null) { 1112 int offset= -1; 1113 int length= -1; 1114 final StringTokenizer tokenizer= new StringTokenizer (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 [] { selection, JDTRefactoringDescriptor.ATTRIBUTE_SELECTION})); 1124 } else 1125 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_SELECTION)); 1126 final String 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 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 |