1 11 package org.eclipse.jdt.internal.corext.refactoring.structure; 12 13 import java.util.ArrayList ; 14 import java.util.Arrays ; 15 import java.util.Collection ; 16 import java.util.HashMap ; 17 import java.util.HashSet ; 18 import java.util.Iterator ; 19 import java.util.LinkedHashMap ; 20 import java.util.List ; 21 import java.util.Map ; 22 import java.util.Set ; 23 24 import org.eclipse.text.edits.TextEdit; 25 import org.eclipse.text.edits.TextEditGroup; 26 27 import org.eclipse.core.runtime.Assert; 28 import org.eclipse.core.runtime.CoreException; 29 import org.eclipse.core.runtime.IProgressMonitor; 30 import org.eclipse.core.runtime.NullProgressMonitor; 31 import org.eclipse.core.runtime.SubProgressMonitor; 32 33 import org.eclipse.ltk.core.refactoring.Change; 34 import org.eclipse.ltk.core.refactoring.IRefactoringStatusEntryComparator; 35 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; 36 import org.eclipse.ltk.core.refactoring.RefactoringStatus; 37 import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry; 38 import org.eclipse.ltk.core.refactoring.TextChange; 39 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments; 40 41 import org.eclipse.jdt.core.Flags; 42 import org.eclipse.jdt.core.ICompilationUnit; 43 import org.eclipse.jdt.core.IField; 44 import org.eclipse.jdt.core.IJavaElement; 45 import org.eclipse.jdt.core.IJavaProject; 46 import org.eclipse.jdt.core.IMethod; 47 import org.eclipse.jdt.core.IType; 48 import org.eclipse.jdt.core.ITypeHierarchy; 49 import org.eclipse.jdt.core.ITypeParameter; 50 import org.eclipse.jdt.core.JavaModelException; 51 import org.eclipse.jdt.core.dom.AST; 52 import org.eclipse.jdt.core.dom.ASTNode; 53 import org.eclipse.jdt.core.dom.ASTParser; 54 import org.eclipse.jdt.core.dom.ASTVisitor; 55 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; 56 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; 57 import org.eclipse.jdt.core.dom.Assignment; 58 import org.eclipse.jdt.core.dom.Block; 59 import org.eclipse.jdt.core.dom.ClassInstanceCreation; 60 import org.eclipse.jdt.core.dom.CompilationUnit; 61 import org.eclipse.jdt.core.dom.ConstructorInvocation; 62 import org.eclipse.jdt.core.dom.EnumDeclaration; 63 import org.eclipse.jdt.core.dom.Expression; 64 import org.eclipse.jdt.core.dom.FieldAccess; 65 import org.eclipse.jdt.core.dom.FieldDeclaration; 66 import org.eclipse.jdt.core.dom.IBinding; 67 import org.eclipse.jdt.core.dom.IMethodBinding; 68 import org.eclipse.jdt.core.dom.ITypeBinding; 69 import org.eclipse.jdt.core.dom.IVariableBinding; 70 import org.eclipse.jdt.core.dom.ImportDeclaration; 71 import org.eclipse.jdt.core.dom.Javadoc; 72 import org.eclipse.jdt.core.dom.MethodDeclaration; 73 import org.eclipse.jdt.core.dom.MethodInvocation; 74 import org.eclipse.jdt.core.dom.Modifier; 75 import org.eclipse.jdt.core.dom.Name; 76 import org.eclipse.jdt.core.dom.ParameterizedType; 77 import org.eclipse.jdt.core.dom.QualifiedName; 78 import org.eclipse.jdt.core.dom.QualifiedType; 79 import org.eclipse.jdt.core.dom.SimpleName; 80 import org.eclipse.jdt.core.dom.SimpleType; 81 import org.eclipse.jdt.core.dom.SingleVariableDeclaration; 82 import org.eclipse.jdt.core.dom.Statement; 83 import org.eclipse.jdt.core.dom.SuperConstructorInvocation; 84 import org.eclipse.jdt.core.dom.ThisExpression; 85 import org.eclipse.jdt.core.dom.Type; 86 import org.eclipse.jdt.core.dom.TypeDeclaration; 87 import org.eclipse.jdt.core.dom.TypeDeclarationStatement; 88 import org.eclipse.jdt.core.dom.TypeParameter; 89 import org.eclipse.jdt.core.dom.VariableDeclarationFragment; 90 import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword; 91 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; 92 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; 93 import org.eclipse.jdt.core.dom.rewrite.ListRewrite; 94 import org.eclipse.jdt.core.refactoring.IJavaRefactorings; 95 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor; 96 import org.eclipse.jdt.core.search.IJavaSearchConstants; 97 import org.eclipse.jdt.core.search.SearchMatch; 98 import org.eclipse.jdt.core.search.SearchPattern; 99 100 import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings; 101 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility; 102 import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory; 103 import org.eclipse.jdt.internal.corext.dom.ASTNodes; 104 import org.eclipse.jdt.internal.corext.dom.Bindings; 105 import org.eclipse.jdt.internal.corext.dom.ModifierRewrite; 106 import org.eclipse.jdt.internal.corext.refactoring.Checks; 107 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor; 108 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment; 109 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments; 110 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; 111 import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory; 112 import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine2; 113 import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup; 114 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext; 115 import org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange; 116 import org.eclipse.jdt.internal.corext.refactoring.changes.CreateCompilationUnitChange; 117 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange; 118 import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring; 119 import org.eclipse.jdt.internal.corext.refactoring.structure.MemberVisibilityAdjustor.OutgoingMemberVisibilityAdjustment; 120 import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil; 121 import org.eclipse.jdt.internal.corext.refactoring.util.JavadocUtil; 122 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser; 123 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil; 124 import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager; 125 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 126 import org.eclipse.jdt.internal.corext.util.JdtFlags; 127 import org.eclipse.jdt.internal.corext.util.Messages; 128 import org.eclipse.jdt.internal.corext.util.SearchUtils; 129 import org.eclipse.jdt.internal.corext.util.Strings; 130 131 import org.eclipse.jdt.ui.CodeGeneration; 132 import org.eclipse.jdt.ui.JavaElementLabels; 133 134 import org.eclipse.jdt.internal.ui.JavaPlugin; 135 import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings; 136 import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider; 137 138 public final class MoveInnerToTopRefactoring extends ScriptableRefactoring { 139 140 private static final String ATTRIBUTE_FIELD= "field"; private static final String ATTRIBUTE_MANDATORY= "mandatory"; private static final String ATTRIBUTE_POSSIBLE= "possible"; private static final String ATTRIBUTE_FINAL= "final"; private static final String ATTRIBUTE_FIELD_NAME= "fieldName"; private static final String ATTRIBUTE_PARAMETER_NAME= "parameterName"; 147 private static class MemberAccessNodeCollector extends ASTVisitor { 148 149 private final List fFieldAccesses= new ArrayList (0); 150 151 private final ITypeHierarchy fHierarchy; 152 153 private final List fMethodAccesses= new ArrayList (0); 154 155 private final List fSimpleNames= new ArrayList (0); 156 157 MemberAccessNodeCollector(ITypeHierarchy hierarchy) { 158 Assert.isNotNull(hierarchy); 159 fHierarchy= hierarchy; 160 } 161 162 FieldAccess[] getFieldAccesses() { 163 return (FieldAccess[]) fFieldAccesses.toArray(new FieldAccess[fFieldAccesses.size()]); 164 } 165 166 MethodInvocation[] getMethodInvocations() { 167 return (MethodInvocation[]) fMethodAccesses.toArray(new MethodInvocation[fMethodAccesses.size()]); 168 } 169 170 SimpleName[] getSimpleFieldNames() { 171 return (SimpleName[]) fSimpleNames.toArray(new SimpleName[fSimpleNames.size()]); 172 } 173 174 public boolean visit(FieldAccess node) { 175 final ITypeBinding declaring= MoveInnerToTopRefactoring.getDeclaringTypeBinding(node); 176 if (declaring != null) { 177 final IType type= (IType) declaring.getJavaElement(); 178 if (type != null && fHierarchy.contains(type)) 179 fFieldAccesses.add(node); 180 } 181 return super.visit(node); 182 } 183 184 public boolean visit(MethodInvocation node) { 185 final ITypeBinding declaring= MoveInnerToTopRefactoring.getDeclaringTypeBinding(node); 186 if (declaring != null) { 187 final IType type= (IType) declaring.getJavaElement(); 188 if (type != null && fHierarchy.contains(type)) 189 fMethodAccesses.add(node); 190 } 191 return super.visit(node); 192 } 193 194 public boolean visit(SimpleName node) { 195 if (node.getParent() instanceof QualifiedName) 196 return super.visit(node); 197 IBinding binding= node.resolveBinding(); 198 if (binding instanceof IVariableBinding) { 199 IVariableBinding variable= (IVariableBinding) binding; 200 ITypeBinding declaring= variable.getDeclaringClass(); 201 if (variable.isField() && declaring != null) { 202 final IType type= (IType) declaring.getJavaElement(); 203 if (type != null && fHierarchy.contains(type)) { 204 fSimpleNames.add(node); 205 return false; 206 } 207 } 208 } 209 return super.visit(node); 210 } 211 212 public boolean visit(ThisExpression node) { 213 final Name qualifier= node.getQualifier(); 214 if (qualifier != null) { 215 final ITypeBinding binding= qualifier.resolveTypeBinding(); 216 if (binding != null) { 217 final IType type= (IType) binding.getJavaElement(); 218 if (type != null && fHierarchy.contains(type)) { 219 fSimpleNames.add(qualifier); 220 return false; 221 } 222 } 223 } 224 return super.visit(node); 225 } 226 } 227 228 private class TypeReferenceQualifier extends ASTVisitor { 229 230 private final TextEditGroup fGroup; 231 232 private final ITypeBinding fTypeBinding; 233 234 public TypeReferenceQualifier(final ITypeBinding type, final TextEditGroup group) { 235 Assert.isNotNull(type); 236 Assert.isNotNull(type.getDeclaringClass()); 237 fTypeBinding= type; 238 fGroup= group; 239 } 240 241 public boolean visit(final ClassInstanceCreation node) { 242 Assert.isNotNull(node); 243 if (fCreateInstanceField) { 244 final AST ast= node.getAST(); 245 final Type type= node.getType(); 246 final ITypeBinding binding= type.resolveBinding(); 247 if (binding != null && binding.getDeclaringClass() != null && !Bindings.equals(binding, fTypeBinding) && fSourceRewrite.getRoot().findDeclaringNode(binding) != null) { 248 if (!Modifier.isStatic(binding.getModifiers())) { 249 Expression expression= null; 250 if (fCodeGenerationSettings.useKeywordThis || fEnclosingInstanceFieldName.equals(fNameForEnclosingInstanceConstructorParameter)) { 251 final FieldAccess access= ast.newFieldAccess(); 252 access.setExpression(ast.newThisExpression()); 253 access.setName(ast.newSimpleName(fEnclosingInstanceFieldName)); 254 expression= access; 255 } else 256 expression= ast.newSimpleName(fEnclosingInstanceFieldName); 257 if (node.getExpression() != null) 258 fSourceRewrite.getImportRemover().registerRemovedNode(node.getExpression()); 259 fSourceRewrite.getASTRewrite().set(node, ClassInstanceCreation.EXPRESSION_PROPERTY, expression, fGroup); 260 } else 261 addTypeQualification(type, fSourceRewrite, fGroup); 262 } 263 } 264 return true; 265 } 266 267 public boolean visit(final QualifiedType node) { 268 Assert.isNotNull(node); 269 return false; 270 } 271 272 public boolean visit(final SimpleType node) { 273 Assert.isNotNull(node); 274 if (!(node.getParent() instanceof ClassInstanceCreation)) { 275 final ITypeBinding binding= node.resolveBinding(); 276 if (binding != null) { 277 final ITypeBinding declaring= binding.getDeclaringClass(); 278 if (declaring != null && !Bindings.equals(declaring, fTypeBinding.getDeclaringClass()) && !Bindings.equals(binding, fTypeBinding) && fSourceRewrite.getRoot().findDeclaringNode(binding) != null && Modifier.isStatic(binding.getModifiers())) 279 addTypeQualification(node, fSourceRewrite, fGroup); 280 } 281 } 282 return super.visit(node); 283 } 284 285 public boolean visit(final ThisExpression node) { 286 Assert.isNotNull(node); 287 final Name name= node.getQualifier(); 288 if (name != null && name.isSimpleName()) { 289 final AST ast= node.getAST(); 290 Expression expression= null; 291 if (fCodeGenerationSettings.useKeywordThis || fEnclosingInstanceFieldName.equals(fNameForEnclosingInstanceConstructorParameter)) { 292 final FieldAccess access= ast.newFieldAccess(); 293 access.setExpression(ast.newThisExpression()); 294 access.setName(ast.newSimpleName(fEnclosingInstanceFieldName)); 295 expression= access; 296 } else 297 expression= ast.newSimpleName(fEnclosingInstanceFieldName); 298 fSourceRewrite.getASTRewrite().replace(node, expression, null); 299 } 300 return super.visit(node); 301 } 302 } 303 304 private static void addTypeParameters(final CompilationUnit unit, final IType type, final Map map) throws JavaModelException { 305 Assert.isNotNull(unit); 306 Assert.isNotNull(type); 307 Assert.isNotNull(map); 308 final AbstractTypeDeclaration declaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(type, unit); 309 if (declaration instanceof TypeDeclaration) { 310 ITypeBinding binding= null; 311 TypeParameter parameter= null; 312 for (final Iterator iterator= ((TypeDeclaration) declaration).typeParameters().iterator(); iterator.hasNext();) { 313 parameter= (TypeParameter) iterator.next(); 314 binding= parameter.resolveBinding(); 315 if (binding != null && !map.containsKey(binding.getKey())) 316 map.put(binding.getKey(), binding); 317 } 318 final IType declaring= type.getDeclaringType(); 319 if (declaring != null && !Flags.isStatic(type.getFlags())) 320 addTypeParameters(unit, declaring, map); 321 } 322 } 323 324 private static boolean containsNonStatic(FieldAccess[] accesses) { 325 for (int i= 0; i < accesses.length; i++) { 326 if (!isStatic(accesses[i])) 327 return true; 328 } 329 return false; 330 } 331 332 private static boolean containsNonStatic(MethodInvocation[] invocations) { 333 for (int i= 0; i < invocations.length; i++) { 334 if (!isStatic(invocations[i])) 335 return true; 336 } 337 return false; 338 } 339 340 private static boolean containsNonStatic(SimpleName[] fieldNames) { 341 for (int i= 0; i < fieldNames.length; i++) { 342 if (!isStaticFieldName(fieldNames[i])) 343 return true; 344 } 345 return false; 346 } 347 348 private static boolean containsStatusEntry(final RefactoringStatus status, final RefactoringStatusEntry other) { 349 return status.getEntries(new IRefactoringStatusEntryComparator() { 350 351 public final int compare(final RefactoringStatusEntry entry1, final RefactoringStatusEntry entry2) { 352 return entry1.getMessage().compareTo(entry2.getMessage()); 353 } 354 }, other).length > 0; 355 } 356 357 private static AbstractTypeDeclaration findTypeDeclaration(IType enclosing, AbstractTypeDeclaration[] declarations) { 358 String typeName= enclosing.getElementName(); 359 for (int i= 0; i < declarations.length; i++) { 360 AbstractTypeDeclaration declaration= declarations[i]; 361 if (declaration.getName().getIdentifier().equals(typeName)) 362 return declaration; 363 } 364 return null; 365 } 366 367 private static AbstractTypeDeclaration findTypeDeclaration(IType type, CompilationUnit unit) { 368 final List types= getDeclaringTypes(type); 369 types.add(type); 370 AbstractTypeDeclaration[] declarations= (AbstractTypeDeclaration[]) unit.types().toArray(new AbstractTypeDeclaration[unit.types().size()]); 371 AbstractTypeDeclaration declaration= null; 372 for (final Iterator iterator= types.iterator(); iterator.hasNext();) { 373 IType enclosing= (IType) iterator.next(); 374 declaration= findTypeDeclaration(enclosing, declarations); 375 Assert.isNotNull(declaration); 376 declarations= getAbstractTypeDeclarations(declaration); 377 } 378 Assert.isNotNull(declaration); 379 return declaration; 380 } 381 382 public static AbstractTypeDeclaration[] getAbstractTypeDeclarations(final AbstractTypeDeclaration declaration) { 383 int typeCount= 0; 384 for (Iterator iterator= declaration.bodyDeclarations().listIterator(); iterator.hasNext();) { 385 if (iterator.next() instanceof AbstractTypeDeclaration) { 386 typeCount++; 387 } 388 } 389 AbstractTypeDeclaration[] declarations= new AbstractTypeDeclaration[typeCount]; 390 int next= 0; 391 for (final Iterator iterator= declaration.bodyDeclarations().listIterator(); iterator.hasNext();) { 392 Object object= iterator.next(); 393 if (object instanceof AbstractTypeDeclaration) { 394 declarations[next++]= (AbstractTypeDeclaration) object; 395 } 396 } 397 return declarations; 398 } 399 400 private static ITypeBinding getDeclaringTypeBinding(FieldAccess fieldAccess) { 401 IVariableBinding varBinding= fieldAccess.resolveFieldBinding(); 402 if (varBinding == null) 403 return null; 404 return varBinding.getDeclaringClass(); 405 } 406 407 private static ITypeBinding getDeclaringTypeBinding(MethodInvocation methodInvocation) { 408 IMethodBinding binding= methodInvocation.resolveMethodBinding(); 409 if (binding == null) 410 return null; 411 return binding.getDeclaringClass(); 412 } 413 414 private static List getDeclaringTypes(IType type) { 416 IType declaringType= type.getDeclaringType(); 417 if (declaringType == null) 418 return new ArrayList (0); 419 List result= getDeclaringTypes(declaringType); 420 result.add(declaringType); 421 return result; 422 } 423 424 private static String [] getFieldNames(IType type) { 425 try { 426 IField[] fields= type.getFields(); 427 List result= new ArrayList (fields.length); 428 for (int i= 0; i < fields.length; i++) { 429 result.add(fields[i].getElementName()); 430 } 431 return (String []) result.toArray(new String [result.size()]); 432 } catch (JavaModelException e) { 433 return null; 434 } 435 } 436 437 private static Set getMergedSet(Set s1, Set s2) { 438 Set result= new HashSet (); 439 result.addAll(s1); 440 result.addAll(s2); 441 return result; 442 } 443 444 private static String [] getParameterNamesOfAllConstructors(IType type) throws JavaModelException { 445 IMethod[] constructors= JavaElementUtil.getAllConstructors(type); 446 Set result= new HashSet (); 447 for (int i= 0; i < constructors.length; i++) { 448 result.addAll(Arrays.asList(constructors[i].getParameterNames())); 449 } 450 return (String []) result.toArray(new String [result.size()]); 451 } 452 453 private static ASTNode[] getReferenceNodesIn(CompilationUnit cuNode, Map references, ICompilationUnit cu) { 454 SearchMatch[] results= (SearchMatch[]) references.get(cu); 455 if (results == null) 456 return new ASTNode[0]; 457 return ASTNodeSearchUtil.getAstNodes(results, cuNode); 458 } 459 460 private static boolean isCorrespondingTypeBinding(ITypeBinding binding, IType type) { 461 if (binding == null) 462 return false; 463 return Bindings.getFullyQualifiedName(binding).equals(JavaElementUtil.createSignature(type)); 464 } 465 466 private static boolean isStatic(FieldAccess access) { 467 IVariableBinding fieldBinding= access.resolveFieldBinding(); 468 if (fieldBinding == null) 469 return false; 470 return JdtFlags.isStatic(fieldBinding); 471 } 472 473 private static boolean isStatic(MethodInvocation invocation) { 474 IMethodBinding methodBinding= invocation.resolveMethodBinding(); 475 if (methodBinding == null) 476 return false; 477 return JdtFlags.isStatic(methodBinding); 478 } 479 480 private static boolean isStaticFieldName(SimpleName name) { 481 IBinding binding= name.resolveBinding(); 482 if (!(binding instanceof IVariableBinding)) 483 return false; 484 IVariableBinding variableBinding= (IVariableBinding) binding; 485 if (!variableBinding.isField()) 486 return false; 487 return JdtFlags.isStatic(variableBinding); 488 } 489 490 private TextChangeManager fChangeManager; 491 492 private CodeGenerationSettings fCodeGenerationSettings; 493 494 private boolean fCreateInstanceField; 495 496 private String fEnclosingInstanceFieldName; 497 498 private boolean fIsInstanceFieldCreationMandatory; 499 500 private boolean fIsInstanceFieldCreationPossible; 501 502 private boolean fMarkInstanceFieldAsFinal; 503 504 private String fNameForEnclosingInstanceConstructorParameter; 505 506 private String fNewSourceOfInputType; 507 508 private CompilationUnitRewrite fSourceRewrite; 509 510 private Collection fStaticImports; 511 512 private IType fType; 513 514 private String fQualifiedTypeName; 515 516 private Collection fTypeImports; 517 518 524 public MoveInnerToTopRefactoring(IType type, CodeGenerationSettings settings) throws JavaModelException { 525 fType= type; 526 fCodeGenerationSettings= settings; 527 fMarkInstanceFieldAsFinal= true; if (fType != null) 529 initialize(); 530 } 531 532 private void initialize() throws JavaModelException { 533 fQualifiedTypeName= JavaModelUtil.concatenateName(fType.getPackageFragment().getElementName(), fType.getElementName()); 534 fEnclosingInstanceFieldName= getInitialNameForEnclosingInstanceField(); 535 fSourceRewrite= new CompilationUnitRewrite(fType.getCompilationUnit()); 536 fIsInstanceFieldCreationPossible= !(JdtFlags.isStatic(fType) || fType.isAnnotation() || fType.isEnum()); 537 fIsInstanceFieldCreationMandatory= fIsInstanceFieldCreationPossible && isInstanceFieldCreationMandatory(); 538 fCreateInstanceField= fIsInstanceFieldCreationMandatory; 539 } 540 541 private void addEnclosingInstanceDeclaration(final AbstractTypeDeclaration declaration, final ASTRewrite rewrite) throws CoreException { 542 Assert.isNotNull(declaration); 543 Assert.isNotNull(rewrite); 544 final AST ast= declaration.getAST(); 545 final VariableDeclarationFragment fragment= ast.newVariableDeclarationFragment(); 546 fragment.setName(ast.newSimpleName(fEnclosingInstanceFieldName)); 547 final FieldDeclaration newField= ast.newFieldDeclaration(fragment); 548 newField.modifiers().addAll(ASTNodeFactory.newModifiers(ast, getEnclosingInstanceAccessModifiers())); 549 newField.setType(createEnclosingType(ast)); 550 final String comment= CodeGeneration.getFieldComment(fType.getCompilationUnit(), declaration.getName().getIdentifier(), fEnclosingInstanceFieldName, StubUtility.getLineDelimiterUsed(fType.getJavaProject())); 551 if (comment != null && comment.length() > 0) { 552 final Javadoc doc= (Javadoc) rewrite.createStringPlaceholder(comment, ASTNode.JAVADOC); 553 newField.setJavadoc(doc); 554 } 555 rewrite.getListRewrite(declaration, declaration.getBodyDeclarationsProperty()).insertFirst(newField, null); 556 } 557 558 private void addEnclosingInstanceTypeParameters(final ITypeBinding[] parameters, final AbstractTypeDeclaration declaration, final ASTRewrite rewrite) { 559 Assert.isNotNull(parameters); 560 Assert.isNotNull(declaration); 561 Assert.isNotNull(rewrite); 562 if (declaration instanceof TypeDeclaration) { 563 final TypeDeclaration type= (TypeDeclaration) declaration; 564 final List existing= type.typeParameters(); 565 final Set names= new HashSet (); 566 TypeParameter parameter= null; 567 for (final Iterator iterator= existing.iterator(); iterator.hasNext();) { 568 parameter= (TypeParameter) iterator.next(); 569 names.add(parameter.getName().getIdentifier()); 570 } 571 final ListRewrite rewriter= rewrite.getListRewrite(type, TypeDeclaration.TYPE_PARAMETERS_PROPERTY); 572 String name= null; 573 for (int index= 0; index < parameters.length; index++) { 574 name= parameters[index].getName(); 575 if (!names.contains(name)) { 576 parameter= type.getAST().newTypeParameter(); 577 parameter.setName(type.getAST().newSimpleName(name)); 578 rewriter.insertLast(parameter, null); 579 } 580 } 581 } 582 } 583 584 private void addImportsToTargetUnit(final ICompilationUnit targetUnit, final IProgressMonitor monitor) throws CoreException, JavaModelException { 585 monitor.beginTask("", 2); try { 587 ImportRewrite rewrite= StubUtility.createImportRewrite(targetUnit, true); 588 if (fTypeImports != null) { 589 ITypeBinding type= null; 590 for (final Iterator iterator= fTypeImports.iterator(); iterator.hasNext();) { 591 type= (ITypeBinding) iterator.next(); 592 rewrite.addImport(type); 593 } 594 } 595 if (fStaticImports != null) { 596 IBinding binding= null; 597 for (final Iterator iterator= fStaticImports.iterator(); iterator.hasNext();) { 598 binding= (IBinding) iterator.next(); 599 rewrite.addStaticImport(binding); 600 } 601 } 602 fTypeImports= null; 603 fStaticImports= null; 604 TextEdit edits= rewrite.rewriteImports(new SubProgressMonitor(monitor, 1)); 605 JavaModelUtil.applyEdit(targetUnit, edits, false, new SubProgressMonitor(monitor, 1)); 606 } finally { 607 monitor.done(); 608 } 609 } 610 611 private void addInheritedTypeQualifications(final AbstractTypeDeclaration declaration, final CompilationUnitRewrite targetRewrite, final TextEditGroup group) { 612 Assert.isNotNull(declaration); 613 Assert.isNotNull(targetRewrite); 614 final CompilationUnit unit= (CompilationUnit) declaration.getRoot(); 615 final ITypeBinding binding= declaration.resolveBinding(); 616 if (binding != null) { 617 Type type= null; 618 if (declaration instanceof TypeDeclaration) { 619 type= ((TypeDeclaration) declaration).getSuperclassType(); 620 if (type != null && unit.findDeclaringNode(binding) != null) 621 addTypeQualification(type, targetRewrite, group); 622 } 623 List types= null; 624 if (declaration instanceof TypeDeclaration) 625 types= ((TypeDeclaration) declaration).superInterfaceTypes(); 626 else if (declaration instanceof EnumDeclaration) 627 types= ((EnumDeclaration) declaration).superInterfaceTypes(); 628 if (types != null) { 629 for (final Iterator iterator= types.iterator(); iterator.hasNext();) { 630 type= (Type) iterator.next(); 631 if (unit.findDeclaringNode(type.resolveBinding()) != null) 632 addTypeQualification(type, targetRewrite, group); 633 } 634 } 635 } 636 } 637 638 private void addParameterToConstructor(final ASTRewrite rewrite, final MethodDeclaration declaration) throws JavaModelException { 639 Assert.isNotNull(rewrite); 640 Assert.isNotNull(declaration); 641 final AST ast= declaration.getAST(); 642 final String name= getNameForEnclosingInstanceConstructorParameter(); 643 final SingleVariableDeclaration variable= ast.newSingleVariableDeclaration(); 644 variable.setType(createEnclosingType(ast)); 645 variable.setName(ast.newSimpleName(name)); 646 rewrite.getListRewrite(declaration, MethodDeclaration.PARAMETERS_PROPERTY).insertFirst(variable, null); 647 JavadocUtil.addParamJavadoc(name, declaration, rewrite, fType.getJavaProject(), null); 648 } 649 650 private void addSimpleTypeQualification(final CompilationUnitRewrite targetRewrite, final ITypeBinding declaring, final SimpleType simpleType, final TextEditGroup group) { 651 Assert.isNotNull(targetRewrite); 652 Assert.isNotNull(declaring); 653 Assert.isNotNull(simpleType); 654 final AST ast= targetRewrite.getRoot().getAST(); 655 if (!(simpleType.getName() instanceof QualifiedName)) { 656 targetRewrite.getASTRewrite().replace(simpleType, ast.newQualifiedType(targetRewrite.getImportRewrite().addImport(declaring, ast), ast.newSimpleName(simpleType.getName().getFullyQualifiedName())), group); 657 targetRewrite.getImportRemover().registerRemovedNode(simpleType); 658 } 659 } 660 661 private void addTypeQualification(final Type type, final CompilationUnitRewrite targetRewrite, final TextEditGroup group) { 662 Assert.isNotNull(type); 663 Assert.isNotNull(targetRewrite); 664 final ITypeBinding binding= type.resolveBinding(); 665 if (binding != null) { 666 final ITypeBinding declaring= binding.getDeclaringClass(); 667 if (declaring != null) { 668 if (type instanceof SimpleType) { 669 final SimpleType simpleType= (SimpleType) type; 670 addSimpleTypeQualification(targetRewrite, declaring, simpleType, group); 671 } else if (type instanceof ParameterizedType) { 672 final ParameterizedType parameterizedType= (ParameterizedType) type; 673 final Type rawType= parameterizedType.getType(); 674 if (rawType instanceof SimpleType) 675 addSimpleTypeQualification(targetRewrite, declaring, (SimpleType) rawType, group); 676 } 677 } 678 } 679 } 680 681 private RefactoringStatus checkConstructorParameterNames() { 682 RefactoringStatus result= new RefactoringStatus(); 683 CompilationUnit cuNode= new RefactoringASTParser(AST.JLS3).parse(fType.getCompilationUnit(), false); 684 MethodDeclaration[] nodes= getConstructorDeclarationNodes(findTypeDeclaration(fType, cuNode)); 685 for (int i= 0; i < nodes.length; i++) { 686 MethodDeclaration constructor= nodes[i]; 687 for (Iterator iter= constructor.parameters().iterator(); iter.hasNext();) { 688 SingleVariableDeclaration param= (SingleVariableDeclaration) iter.next(); 689 if (fEnclosingInstanceFieldName.equals(param.getName().getIdentifier())) { 690 String msg= Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_name_used, new String [] { param.getName().getIdentifier(), fType.getElementName()}); 691 result.addError(msg, JavaStatusContext.create(fType.getCompilationUnit(), param)); 692 } 693 } 694 } 695 return result; 696 } 697 698 public RefactoringStatus checkEnclosingInstanceName(String name) { 699 if (!fCreateInstanceField) 700 return new RefactoringStatus(); 701 RefactoringStatus result= Checks.checkFieldName(name); 702 if (!Checks.startsWithLowerCase(name)) 703 result.addWarning(RefactoringCoreMessages.MoveInnerToTopRefactoring_names_start_lowercase); 704 705 if (fType.getField(name).exists()) { 706 Object [] keys= new String [] { name, fType.getElementName()}; 707 String msg= Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_already_declared, keys); 708 result.addError(msg, JavaStatusContext.create(fType.getField(name))); 709 } 710 return result; 711 } 712 713 public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException { 714 pm.beginTask("", 2); try { 716 RefactoringStatus result= new RefactoringStatus(); 717 718 if (JdtFlags.isStatic(fType)) 719 result.merge(checkEnclosingInstanceName(fEnclosingInstanceFieldName)); 720 721 if (fType.getPackageFragment().getCompilationUnit((JavaModelUtil.getRenamedCUName(fType.getCompilationUnit(), fType.getElementName()))).exists()) { 722 String message= Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_compilation_Unit_exists, new String [] { (JavaModelUtil.getRenamedCUName(fType.getCompilationUnit(), fType.getElementName())), fType.getPackageFragment().getElementName()}); 723 result.addFatalError(message); 724 } 725 result.merge(checkEnclosingInstanceName(fEnclosingInstanceFieldName)); 726 result.merge(Checks.checkCompilationUnitName((JavaModelUtil.getRenamedCUName(fType.getCompilationUnit(), fType.getElementName())))); 727 result.merge(checkConstructorParameterNames()); 728 result.merge(checkTypeNameInPackage()); 729 fChangeManager= createChangeManager(new SubProgressMonitor(pm, 1), result); 730 result.merge(Checks.validateModifiesFiles(ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits()), getValidationContext())); 731 return result; 732 } finally { 733 pm.done(); 734 } 735 } 736 737 public RefactoringStatus checkInitialConditions(IProgressMonitor monitor) throws CoreException { 738 return Checks.checkIfCuBroken(fType); 739 } 740 741 private RefactoringStatus checkTypeNameInPackage() throws JavaModelException { 742 IType type= Checks.findTypeInPackage(fType.getPackageFragment(), fType.getElementName()); 743 if (type == null || !type.exists()) 744 return null; 745 String message= Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_type_exists, new String [] { fType.getElementName(), fType.getPackageFragment().getElementName()}); 746 return RefactoringStatus.createErrorStatus(message); 747 } 748 749 private Expression createAccessExpressionToEnclosingInstanceFieldText(ASTNode node, IBinding binding, AbstractTypeDeclaration declaration) { 750 if (Modifier.isStatic(binding.getModifiers())) 751 return node.getAST().newName(JavaModelUtil.getTypeQualifiedName(fType.getDeclaringType())); 752 else if ((isInAnonymousTypeInsideInputType(node, declaration) || isInLocalTypeInsideInputType(node, declaration) || isInNonStaticMemberTypeInsideInputType(node, declaration))) 753 return createQualifiedReadAccessExpressionForEnclosingInstance(node.getAST()); 754 else 755 return createReadAccessExpressionForEnclosingInstance(node.getAST()); 756 } 757 758 public Change createChange(final IProgressMonitor monitor) throws CoreException { 759 monitor.beginTask(RefactoringCoreMessages.MoveInnerToTopRefactoring_creating_change, 1); 760 final Map arguments= new HashMap (); 761 String project= null; 762 IJavaProject javaProject= fType.getJavaProject(); 763 if (javaProject != null) 764 project= javaProject.getElementName(); 765 final String description= Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_descriptor_description_short, fType.getElementName()); 766 final String header= Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_descriptor_description, new String [] { JavaElementLabels.getElementLabel(fType, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getElementLabel(fType.getParent(), JavaElementLabels.ALL_FULLY_QUALIFIED)}); 767 final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header); 768 comment.addSetting(Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_original_pattern, JavaElementLabels.getElementLabel(fType, JavaElementLabels.ALL_FULLY_QUALIFIED))); 769 final boolean enclosing= fEnclosingInstanceFieldName != null && !"".equals(fEnclosingInstanceFieldName); if (enclosing) 771 comment.addSetting(Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_field_pattern, fEnclosingInstanceFieldName)); 772 if (fNameForEnclosingInstanceConstructorParameter != null && !"".equals(fNameForEnclosingInstanceConstructorParameter)) comment.addSetting(Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_parameter_pattern, fNameForEnclosingInstanceConstructorParameter)); 774 if (enclosing && fMarkInstanceFieldAsFinal) 775 comment.addSetting(RefactoringCoreMessages.MoveInnerToTopRefactoring_declare_final); 776 final JDTRefactoringDescriptor descriptor= new JDTRefactoringDescriptor(IJavaRefactorings.CONVERT_MEMBER_TYPE, project, description, comment.asString(), arguments, RefactoringDescriptor.MULTI_CHANGE | RefactoringDescriptor.STRUCTURAL_CHANGE | JavaRefactoringDescriptor.JAR_REFACTORING | JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT); 777 arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_INPUT, descriptor.elementToHandle(fType)); 778 if (enclosing) 779 arguments.put(ATTRIBUTE_FIELD_NAME, fEnclosingInstanceFieldName); 780 if (fNameForEnclosingInstanceConstructorParameter != null && !"".equals(fNameForEnclosingInstanceConstructorParameter)) arguments.put(ATTRIBUTE_PARAMETER_NAME, fNameForEnclosingInstanceConstructorParameter); 782 arguments.put(ATTRIBUTE_FIELD, Boolean.valueOf(fCreateInstanceField).toString()); 783 arguments.put(ATTRIBUTE_FINAL, Boolean.valueOf(fMarkInstanceFieldAsFinal).toString()); 784 arguments.put(ATTRIBUTE_POSSIBLE, Boolean.valueOf(fIsInstanceFieldCreationPossible).toString()); 785 arguments.put(ATTRIBUTE_MANDATORY, Boolean.valueOf(fIsInstanceFieldCreationMandatory).toString()); 786 final DynamicValidationRefactoringChange result= new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.MoveInnerToTopRefactoring_move_to_Top); 787 result.addAll(fChangeManager.getAllChanges()); 788 result.add(createCompilationUnitForMovedType(new SubProgressMonitor(monitor, 1))); 789 return result; 790 } 791 792 private TextChangeManager createChangeManager(final IProgressMonitor monitor, final RefactoringStatus status) throws CoreException { 793 Assert.isNotNull(monitor); 794 Assert.isNotNull(status); 795 final TextChangeManager manager= new TextChangeManager(); 796 try { 797 monitor.beginTask(RefactoringCoreMessages.MoveInnerToTopRefactoring_creating_preview, 4); 798 final Map rewrites= new HashMap (2); 799 fSourceRewrite.clearASTAndImportRewrites(); 800 rewrites.put(fSourceRewrite.getCu(), fSourceRewrite); 801 final MemberVisibilityAdjustor adjustor= new MemberVisibilityAdjustor(fType.getPackageFragment(), fType); 802 adjustor.setRewrites(rewrites); 803 adjustor.setVisibilitySeverity(RefactoringStatus.WARNING); 804 adjustor.setFailureSeverity(RefactoringStatus.WARNING); 805 adjustor.setStatus(status); 806 adjustor.adjustVisibility(new SubProgressMonitor(monitor, 1)); 807 final Map parameters= new LinkedHashMap (); 808 addTypeParameters(fSourceRewrite.getRoot(), fType, parameters); 809 final ITypeBinding[] bindings= new ITypeBinding[parameters.values().size()]; 810 parameters.values().toArray(bindings); 811 final Map typeReferences= createTypeReferencesMapping(new SubProgressMonitor(monitor, 1), status); 812 Map constructorReferences= null; 813 if (JdtFlags.isStatic(fType)) 814 constructorReferences= new HashMap (0); 815 else 816 constructorReferences= createConstructorReferencesMapping(new SubProgressMonitor(monitor, 1), status); 817 if (fCreateInstanceField) { 818 IType type= fType; 821 ModifierKeyword keyword= null; 822 while ( (type= type.getDeclaringType()) != null) { 823 if ((!adjustor.getAdjustments().containsKey(type)) && (Modifier.isPrivate(type.getFlags()))) 824 adjustor.getAdjustments().put(type, new OutgoingMemberVisibilityAdjustment(type, keyword, RefactoringStatus.createWarningStatus(Messages.format(RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_type_warning, new String [] { MemberVisibilityAdjustor.getLabel(type), MemberVisibilityAdjustor.getLabel(keyword) }), JavaStatusContext.create(type.getCompilationUnit(), type.getSourceRange())))); 825 } 826 } 827 monitor.worked(1); 828 for (final Iterator iterator= getMergedSet(typeReferences.keySet(), constructorReferences.keySet()).iterator(); iterator.hasNext();) { 829 final ICompilationUnit unit= (ICompilationUnit) iterator.next(); 830 final CompilationUnitRewrite targetRewrite= getCompilationUnitRewrite(unit); 831 createCompilationUnitRewrite(bindings, targetRewrite, typeReferences, constructorReferences, adjustor.getAdjustments().containsKey(fType), fType.getCompilationUnit(), unit, false, status, monitor); 832 if (unit.equals(fType.getCompilationUnit())) { 833 try { 834 adjustor.setStatus(new RefactoringStatus()); 835 adjustor.rewriteVisibility(targetRewrite.getCu(), new SubProgressMonitor(monitor, 1)); 836 } finally { 837 adjustor.setStatus(status); 838 } 839 fNewSourceOfInputType= createNewSource(targetRewrite, unit); 840 targetRewrite.clearASTAndImportRewrites(); 841 createCompilationUnitRewrite(bindings, targetRewrite, typeReferences, constructorReferences, adjustor.getAdjustments().containsKey(fType), fType.getCompilationUnit(), unit, true, status, monitor); 842 } 843 adjustor.rewriteVisibility(targetRewrite.getCu(), new SubProgressMonitor(monitor, 1)); 844 manager.manage(unit, targetRewrite.createChange()); 845 } 846 } finally { 847 monitor.done(); 848 } 849 return manager; 850 } 851 852 private Change createCompilationUnitForMovedType(IProgressMonitor pm) throws CoreException { 853 ICompilationUnit newCuWC= null; 854 try { 855 newCuWC= fType.getPackageFragment().getCompilationUnit(JavaModelUtil.getRenamedCUName(fType.getCompilationUnit(), fType.getElementName())).getWorkingCopy(null); 856 String source= createSourceForNewCu(newCuWC, pm); 857 return new CreateCompilationUnitChange(fType.getPackageFragment().getCompilationUnit(JavaModelUtil.getRenamedCUName(fType.getCompilationUnit(), fType.getElementName())), source, null); 858 } finally { 859 if (newCuWC != null) 860 newCuWC.discardWorkingCopy(); 861 } 862 } 863 864 private void createCompilationUnitRewrite(final ITypeBinding[] parameters, final CompilationUnitRewrite targetRewrite, final Map typeReferences, final Map constructorReferences, boolean visibilityWasAdjusted, final ICompilationUnit sourceUnit, final ICompilationUnit targetUnit, final boolean remove, final RefactoringStatus status, final IProgressMonitor monitor) throws CoreException { 865 Assert.isNotNull(parameters); 866 Assert.isNotNull(targetRewrite); 867 Assert.isNotNull(typeReferences); 868 Assert.isNotNull(constructorReferences); 869 Assert.isNotNull(sourceUnit); 870 Assert.isNotNull(targetUnit); 871 final CompilationUnit root= targetRewrite.getRoot(); 872 final ASTRewrite rewrite= targetRewrite.getASTRewrite(); 873 if (targetUnit.equals(sourceUnit)) { 874 final AbstractTypeDeclaration declaration= findTypeDeclaration(fType, root); 875 final TextEditGroup qualifierGroup= fSourceRewrite.createGroupDescription(RefactoringCoreMessages.MoveInnerToTopRefactoring_change_qualifier); 876 ITypeBinding binding= declaration.resolveBinding(); 877 if (!remove) { 878 if (!JdtFlags.isStatic(fType) && fCreateInstanceField) { 879 if (JavaElementUtil.getAllConstructors(fType).length == 0) 880 createConstructor(declaration, rewrite); 881 else 882 modifyConstructors(declaration, rewrite); 883 addInheritedTypeQualifications(declaration, targetRewrite, qualifierGroup); 884 addEnclosingInstanceDeclaration(declaration, rewrite); 885 } 886 fTypeImports= new HashSet (); 887 fStaticImports= new HashSet (); 888 ImportRewriteUtil.collectImports(fType.getJavaProject(), declaration, fTypeImports, fStaticImports, false); 889 if (binding != null) 890 fTypeImports.remove(binding); 891 } 892 addEnclosingInstanceTypeParameters(parameters, declaration, rewrite); 893 modifyAccessToEnclosingInstance(targetRewrite, declaration, status, monitor); 894 if (binding != null) { 895 modifyInterfaceMemberModifiers(binding); 896 final ITypeBinding declaring= binding.getDeclaringClass(); 897 if (declaring != null) 898 declaration.accept(new TypeReferenceQualifier(binding, null)); 899 } 900 final TextEditGroup groupMove= targetRewrite.createGroupDescription(RefactoringCoreMessages.MoveInnerToTopRefactoring_change_label); 901 if (remove) { 902 rewrite.remove(declaration, groupMove); 903 targetRewrite.getImportRemover().registerRemovedNode(declaration); 904 } else { 905 908 int newFlags= JdtFlags.clearFlag(Modifier.STATIC, declaration.getModifiers()); 911 912 if (!visibilityWasAdjusted) { 913 if (Modifier.isPrivate(declaration.getModifiers()) || Modifier.isProtected(declaration.getModifiers())) { 914 newFlags= JdtFlags.clearFlag(Modifier.PROTECTED | Modifier.PRIVATE, newFlags); 915 final RefactoringStatusEntry entry= new RefactoringStatusEntry(RefactoringStatus.WARNING, Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_change_visibility_type_warning, new String [] { BindingLabelProvider.getBindingLabel(binding, JavaElementLabels.ALL_FULLY_QUALIFIED)}), JavaStatusContext.create(fSourceRewrite.getCu())); 916 if (!containsStatusEntry(status, entry)) 917 status.addEntry(entry); 918 } 919 } 920 921 ModifierRewrite.create(rewrite, declaration).setModifiers(newFlags, groupMove); 922 } 923 } 924 ASTNode[] references= getReferenceNodesIn(root, typeReferences, targetUnit); 925 for (int index= 0; index < references.length; index++) 926 updateTypeReference(parameters, references[index], targetRewrite, targetUnit); 927 references= getReferenceNodesIn(root, constructorReferences, targetUnit); 928 for (int index= 0; index < references.length; index++) 929 updateConstructorReference(parameters, references[index], targetRewrite, targetUnit); 930 } 931 932 private void createConstructor(final AbstractTypeDeclaration declaration, final ASTRewrite rewrite) throws CoreException { 933 Assert.isNotNull(declaration); 934 Assert.isNotNull(rewrite); 935 final AST ast= declaration.getAST(); 936 final MethodDeclaration constructor= ast.newMethodDeclaration(); 937 constructor.setConstructor(true); 938 constructor.setName(ast.newSimpleName(declaration.getName().getIdentifier())); 939 final String comment= CodeGeneration.getMethodComment(fType.getCompilationUnit(), fType.getElementName(), fType.getElementName(), getNewConstructorParameterNames(), new String [0], null, null, StubUtility.getLineDelimiterUsed(fType.getJavaProject())); 940 if (comment != null && comment.length() > 0) { 941 final Javadoc doc= (Javadoc) rewrite.createStringPlaceholder(comment, ASTNode.JAVADOC); 942 constructor.setJavadoc(doc); 943 } 944 if (fCreateInstanceField) { 945 final SingleVariableDeclaration variable= ast.newSingleVariableDeclaration(); 946 final String name= getNameForEnclosingInstanceConstructorParameter(); 947 variable.setName(ast.newSimpleName(name)); 948 variable.setType(createEnclosingType(ast)); 949 constructor.parameters().add(variable); 950 final Block body= ast.newBlock(); 951 final Assignment assignment= ast.newAssignment(); 952 if (fCodeGenerationSettings.useKeywordThis || fEnclosingInstanceFieldName.equals(fNameForEnclosingInstanceConstructorParameter)) { 953 final FieldAccess access= ast.newFieldAccess(); 954 access.setExpression(ast.newThisExpression()); 955 access.setName(ast.newSimpleName(fEnclosingInstanceFieldName)); 956 assignment.setLeftHandSide(access); 957 } else 958 assignment.setLeftHandSide(ast.newSimpleName(fEnclosingInstanceFieldName)); 959 assignment.setRightHandSide(ast.newSimpleName(name)); 960 final Statement statement= ast.newExpressionStatement(assignment); 961 body.statements().add(statement); 962 constructor.setBody(body); 963 } else 964 constructor.setBody(ast.newBlock()); 965 rewrite.getListRewrite(declaration, declaration.getBodyDeclarationsProperty()).insertFirst(constructor, null); 966 } 967 968 private Map createConstructorReferencesMapping(IProgressMonitor pm, RefactoringStatus status) throws JavaModelException { 970 SearchResultGroup[] groups= ConstructorReferenceFinder.getConstructorReferences(fType, pm, status); 971 Map result= new HashMap (); 972 for (int i= 0; i < groups.length; i++) { 973 SearchResultGroup group= groups[i]; 974 ICompilationUnit cu= group.getCompilationUnit(); 975 if (cu == null) 976 continue; 977 result.put(cu, group.getSearchResults()); 978 } 979 return result; 980 } 981 982 private Expression createEnclosingInstanceCreationString(final ASTNode node, final ICompilationUnit cu) throws JavaModelException { 983 Assert.isTrue((node instanceof ClassInstanceCreation) || (node instanceof SuperConstructorInvocation)); 984 Assert.isNotNull(cu); 985 Expression expression= null; 986 if (node instanceof ClassInstanceCreation) 987 expression= ((ClassInstanceCreation) node).getExpression(); 988 else 989 expression= ((SuperConstructorInvocation) node).getExpression(); 990 final AST ast= node.getAST(); 991 if (expression != null) 992 return expression; 993 else if (JdtFlags.isStatic(fType)) 994 return null; 995 else if (isInsideSubclassOfDeclaringType(node)) 996 return ast.newThisExpression(); 997 else if ((node.getStartPosition() >= fType.getSourceRange().getOffset() && ASTNodes.getExclusiveEnd(node) <= fType.getSourceRange().getOffset() + fType.getSourceRange().getLength())) { 998 if (fCodeGenerationSettings.useKeywordThis || fEnclosingInstanceFieldName.equals(fNameForEnclosingInstanceConstructorParameter)) { 999 final FieldAccess access= ast.newFieldAccess(); 1000 access.setExpression(ast.newThisExpression()); 1001 access.setName(ast.newSimpleName(fEnclosingInstanceFieldName)); 1002 return access; 1003 } else 1004 return ast.newSimpleName(fEnclosingInstanceFieldName); 1005 } else if (isInsideTypeNestedInDeclaringType(node)) { 1006 final ThisExpression qualified= ast.newThisExpression(); 1007 qualified.setQualifier(ast.newSimpleName(fType.getDeclaringType().getElementName())); 1008 return qualified; 1009 } 1010 return null; 1011 } 1012 1013 private Type createEnclosingType(final AST ast) throws JavaModelException { 1014 Assert.isNotNull(ast); 1015 final ITypeParameter[] parameters= fType.getDeclaringType().getTypeParameters(); 1016 final Type type= ASTNodeFactory.newType(ast, JavaModelUtil.getTypeQualifiedName(fType.getDeclaringType())); 1017 if (parameters.length > 0) { 1018 final ParameterizedType parameterized= ast.newParameterizedType(type); 1019 for (int index= 0; index < parameters.length; index++) 1020 parameterized.typeArguments().add(ast.newSimpleType(ast.newSimpleName(parameters[index].getElementName()))); 1021 return parameterized; 1022 } 1023 return type; 1024 } 1025 1026 private String createNewSource(final CompilationUnitRewrite targetRewrite, final ICompilationUnit unit) throws CoreException, JavaModelException { 1027 Assert.isNotNull(targetRewrite); 1028 Assert.isNotNull(unit); 1029 TextChange change= targetRewrite.createChange(); 1030 if (change == null) 1031 change= new CompilationUnitChange("", unit); final String source= change.getPreviewContent(new NullProgressMonitor()); 1033 final ASTParser parser= ASTParser.newParser(AST.JLS3); 1034 parser.setProject(fType.getJavaProject()); 1035 parser.setResolveBindings(false); 1036 parser.setSource(source.toCharArray()); 1037 final AbstractTypeDeclaration declaration= findTypeDeclaration(fType, (CompilationUnit) parser.createAST(null)); 1038 return source.substring(declaration.getStartPosition(), ASTNodes.getExclusiveEnd(declaration)); 1039 } 1040 1041 private Expression createQualifiedReadAccessExpressionForEnclosingInstance(AST ast) { 1042 ThisExpression expression= ast.newThisExpression(); 1043 expression.setQualifier(ast.newName(new String [] { fType.getElementName()})); 1044 FieldAccess access= ast.newFieldAccess(); 1045 access.setExpression(expression); 1046 access.setName(ast.newSimpleName(fEnclosingInstanceFieldName)); 1047 return access; 1048 } 1049 1050 private Expression createReadAccessExpressionForEnclosingInstance(AST ast) { 1051 if (fCodeGenerationSettings.useKeywordThis || fEnclosingInstanceFieldName.equals(fNameForEnclosingInstanceConstructorParameter)) { 1052 final FieldAccess access= ast.newFieldAccess(); 1053 access.setExpression(ast.newThisExpression()); 1054 access.setName(ast.newSimpleName(fEnclosingInstanceFieldName)); 1055 return access; 1056 } 1057 return ast.newSimpleName(fEnclosingInstanceFieldName); 1058 } 1059 1060 private String createSourceForNewCu(final ICompilationUnit unit, final IProgressMonitor monitor) throws CoreException { 1061 Assert.isNotNull(unit); 1062 Assert.isNotNull(monitor); 1063 try { 1064 monitor.beginTask("", 2); final String separator= StubUtility.getLineDelimiterUsed(fType.getJavaProject()); 1066 final String block= getAlignedSourceBlock(unit, fNewSourceOfInputType); 1067 String content= CodeGeneration.getCompilationUnitContent(unit, null, block, separator); 1068 if (content == null || block.startsWith("/*") || block.startsWith("//")) { final StringBuffer buffer= new StringBuffer (); 1070 if (!fType.getPackageFragment().isDefaultPackage()) { 1071 buffer.append("package ").append(fType.getPackageFragment().getElementName()).append(';'); } 1073 buffer.append(separator).append(separator); 1074 buffer.append(block); 1075 content= buffer.toString(); 1076 } 1077 unit.getBuffer().setContents(content); 1078 addImportsToTargetUnit(unit, new SubProgressMonitor(monitor, 1)); 1079 } finally { 1080 monitor.done(); 1081 } 1082 return unit.getSource(); 1083 } 1084 1085 private Map createTypeReferencesMapping(IProgressMonitor pm, RefactoringStatus status) throws JavaModelException { 1087 final RefactoringSearchEngine2 engine= new RefactoringSearchEngine2(SearchPattern.createPattern(fType, IJavaSearchConstants.ALL_OCCURRENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE)); 1088 engine.setFiltering(true, true); 1089 engine.setScope(RefactoringScopeFactory.create(fType)); 1090 engine.setStatus(status); 1091 engine.searchPattern(new SubProgressMonitor(pm, 1)); 1092 final SearchResultGroup[] groups= (SearchResultGroup[]) engine.getResults(); 1093 Map result= new HashMap (); 1094 for (int i= 0; i < groups.length; i++) { 1095 SearchResultGroup group= groups[i]; 1096 ICompilationUnit cu= group.getCompilationUnit(); 1097 if (cu == null) 1098 continue; 1099 result.put(cu, group.getSearchResults()); 1100 } 1101 return result; 1102 } 1103 1104 private String getAlignedSourceBlock(final ICompilationUnit unit, final String block) { 1105 Assert.isNotNull(block); 1106 final String [] lines= Strings.convertIntoLines(block); 1107 Strings.trimIndentation(lines, unit.getJavaProject(), false); 1108 return Strings.concatenate(lines, StubUtility.getLineDelimiterUsed(fType.getJavaProject())); 1109 } 1110 1111 private CompilationUnitRewrite getCompilationUnitRewrite(final ICompilationUnit unit) { 1112 Assert.isNotNull(unit); 1113 if (unit.equals(fType.getCompilationUnit())) 1114 return fSourceRewrite; 1115 return new CompilationUnitRewrite(unit); 1116 } 1117 1118 private MethodDeclaration[] getConstructorDeclarationNodes(final AbstractTypeDeclaration declaration) { 1119 if (declaration instanceof TypeDeclaration) { 1120 final MethodDeclaration[] declarations= ((TypeDeclaration) declaration).getMethods(); 1121 final List result= new ArrayList (2); 1122 for (int index= 0; index < declarations.length; index++) { 1123 if (declarations[index].isConstructor()) 1124 result.add(declarations[index]); 1125 } 1126 return (MethodDeclaration[]) result.toArray(new MethodDeclaration[result.size()]); 1127 } 1128 return new MethodDeclaration[] {}; 1129 } 1130 1131 public boolean getCreateInstanceField() { 1132 return fCreateInstanceField; 1133 } 1134 1135 private int getEnclosingInstanceAccessModifiers() { 1136 if (fMarkInstanceFieldAsFinal) 1137 return Modifier.PRIVATE | Modifier.FINAL; 1138 else 1139 return Modifier.PRIVATE; 1140 } 1141 1142 public String getEnclosingInstanceName() { 1143 return fEnclosingInstanceFieldName; 1144 } 1145 1146 private String getInitialNameForEnclosingInstanceField() { 1147 IType enclosingType= fType.getDeclaringType(); 1148 if (enclosingType == null) 1149 return ""; String [] suggestedNames= StubUtility.getFieldNameSuggestions(fType.getDeclaringType(), getEnclosingInstanceAccessModifiers(), getFieldNames(fType)); 1151 if (suggestedNames.length > 0) 1152 return suggestedNames[0]; 1153 String name= enclosingType.getElementName(); 1154 if (name.equals("")) return ""; return Character.toLowerCase(name.charAt(0)) + name.substring(1); 1157 } 1158 1159 public IType getInputType() { 1160 return fType; 1161 } 1162 1163 1166 public String getName() { 1167 return RefactoringCoreMessages.MoveInnerToTopRefactoring_name; 1168 } 1169 1170 private String getNameForEnclosingInstanceConstructorParameter() throws JavaModelException { 1171 if (fNameForEnclosingInstanceConstructorParameter != null) 1172 return fNameForEnclosingInstanceConstructorParameter; 1173 1174 String [] suggestedNames= StubUtility.getArgumentNameSuggestions(fType.getDeclaringType(), getParameterNamesOfAllConstructors(fType)); 1175 if (suggestedNames.length > 0) 1176 fNameForEnclosingInstanceConstructorParameter= suggestedNames[0]; 1177 else 1178 fNameForEnclosingInstanceConstructorParameter= fEnclosingInstanceFieldName; 1179 return fNameForEnclosingInstanceConstructorParameter; 1180 } 1181 1182 private String [] getNewConstructorParameterNames() throws JavaModelException { 1183 if (!fCreateInstanceField) 1184 return new String [0]; 1185 return new String [] { getNameForEnclosingInstanceConstructorParameter()}; 1186 } 1187 1188 private ASTNode getNewQualifiedNameNode(ITypeBinding[] parameters, Name name) { 1189 final AST ast= name.getAST(); 1190 boolean raw= false; 1191 final ITypeBinding binding= name.resolveTypeBinding(); 1192 if (binding != null && binding.isRawType()) 1193 raw= true; 1194 if (parameters != null && parameters.length > 0 && !raw) { 1195 final ParameterizedType type= ast.newParameterizedType(ast.newSimpleType(ast.newName(fQualifiedTypeName))); 1196 for (int index= 0; index < parameters.length; index++) 1197 type.typeArguments().add(ast.newSimpleType(ast.newSimpleName(parameters[index].getName()))); 1198 return type; 1199 } 1200 return ast.newName(fQualifiedTypeName); 1201 } 1202 1203 private ASTNode getNewUnqualifiedTypeNode(ITypeBinding[] parameters, Name name) { 1204 final AST ast= name.getAST(); 1205 boolean raw= false; 1206 final ITypeBinding binding= name.resolveTypeBinding(); 1207 if (binding != null && binding.isRawType()) 1208 raw= true; 1209 if (parameters != null && parameters.length > 0 && !raw) { 1210 final ParameterizedType type= ast.newParameterizedType(ast.newSimpleType(ast.newSimpleName(fType.getElementName()))); 1211 for (int index= 0; index < parameters.length; index++) 1212 type.typeArguments().add(ast.newSimpleType(ast.newSimpleName(parameters[index].getName()))); 1213 return type; 1214 } 1215 return ast.newSimpleType(ast.newSimpleName(fType.getElementName())); 1216 } 1217 1218 private boolean insertExpressionAsParameter(ClassInstanceCreation cic, ASTRewrite rewrite, ICompilationUnit cu, TextEditGroup group) throws JavaModelException { 1219 final Expression expression= createEnclosingInstanceCreationString(cic, cu); 1220 if (expression == null) 1221 return false; 1222 rewrite.getListRewrite(cic, ClassInstanceCreation.ARGUMENTS_PROPERTY).insertFirst(expression, group); 1223 return true; 1224 } 1225 1226 private boolean insertExpressionAsParameter(SuperConstructorInvocation sci, ASTRewrite rewrite, ICompilationUnit cu, TextEditGroup group) throws JavaModelException { 1227 final Expression expression= createEnclosingInstanceCreationString(sci, cu); 1228 if (expression == null) 1229 return false; 1230 rewrite.getListRewrite(sci, SuperConstructorInvocation.ARGUMENTS_PROPERTY).insertFirst(expression, group); 1231 return true; 1232 } 1233 1234 public boolean isCreatingInstanceFieldMandatory() { 1235 return fIsInstanceFieldCreationMandatory; 1236 } 1237 1238 public boolean isCreatingInstanceFieldPossible() { 1239 return fIsInstanceFieldCreationPossible; 1240 } 1241 1242 private boolean isInAnonymousTypeInsideInputType(ASTNode node, AbstractTypeDeclaration declaration) { 1243 final AnonymousClassDeclaration anonymous= (AnonymousClassDeclaration) ASTNodes.getParent(node, AnonymousClassDeclaration.class); 1244 return anonymous != null && ASTNodes.isParent(anonymous, declaration); 1245 } 1246 1247 private boolean isInLocalTypeInsideInputType(ASTNode node, AbstractTypeDeclaration declaration) { 1248 final TypeDeclarationStatement statement= (TypeDeclarationStatement) ASTNodes.getParent(node, TypeDeclarationStatement.class); 1249 return statement != null && ASTNodes.isParent(statement, declaration); 1250 } 1251 1252 private boolean isInNonStaticMemberTypeInsideInputType(ASTNode node, AbstractTypeDeclaration declaration) { 1253 final AbstractTypeDeclaration nested= (AbstractTypeDeclaration) ASTNodes.getParent(node, AbstractTypeDeclaration.class); 1254 return nested != null && !declaration.equals(nested) && !Modifier.isStatic(nested.getFlags()) && ASTNodes.isParent(nested, declaration); 1255 } 1256 1257 private boolean isInsideSubclassOfDeclaringType(ASTNode node) { 1258 Assert.isTrue((node instanceof ClassInstanceCreation) || (node instanceof SuperConstructorInvocation)); 1259 final AbstractTypeDeclaration declaration= (AbstractTypeDeclaration) ASTNodes.getParent(node, AbstractTypeDeclaration.class); 1260 Assert.isNotNull(declaration); 1261 1262 final AnonymousClassDeclaration anonymous= (AnonymousClassDeclaration) ASTNodes.getParent(node, AnonymousClassDeclaration.class); 1263 boolean isAnonymous= anonymous != null && ASTNodes.isParent(anonymous, declaration); 1264 if (isAnonymous) 1265 return anonymous != null && isSubclassBindingOfEnclosingType(anonymous.resolveBinding()); 1266 return isSubclassBindingOfEnclosingType(declaration.resolveBinding()); 1267 } 1268 1269 private boolean isInsideTypeNestedInDeclaringType(ASTNode node) { 1270 Assert.isTrue((node instanceof ClassInstanceCreation) || (node instanceof SuperConstructorInvocation)); 1271 final AbstractTypeDeclaration declaration= (AbstractTypeDeclaration) ASTNodes.getParent(node, AbstractTypeDeclaration.class); 1272 Assert.isNotNull(declaration); 1273 ITypeBinding enclosing= declaration.resolveBinding(); 1274 while (enclosing != null) { 1275 if (isCorrespondingTypeBinding(enclosing, fType.getDeclaringType())) 1276 return true; 1277 enclosing= enclosing.getDeclaringClass(); 1278 } 1279 return false; 1280 } 1281 1282 private boolean isInstanceFieldCreationMandatory() throws JavaModelException { 1283 final MemberAccessNodeCollector collector= new MemberAccessNodeCollector(fType.getDeclaringType().newSupertypeHierarchy(new NullProgressMonitor())); 1284 findTypeDeclaration(fType, fSourceRewrite.getRoot()).accept(collector); 1285 return containsNonStatic(collector.getFieldAccesses()) || containsNonStatic(collector.getMethodInvocations()) || containsNonStatic(collector.getSimpleFieldNames()); 1286 } 1287 1288 public boolean isInstanceFieldMarkedFinal() { 1289 return fMarkInstanceFieldAsFinal; 1290 } 1291 1292 private boolean isSubclassBindingOfEnclosingType(ITypeBinding binding) { 1293 while (binding != null) { 1294 if (isCorrespondingTypeBinding(binding, fType.getDeclaringType())) 1295 return true; 1296 binding= binding.getSuperclass(); 1297 } 1298 return false; 1299 } 1300 1301 1306 private void modifyAccessToEnclosingInstance(final CompilationUnitRewrite targetRewrite, final AbstractTypeDeclaration declaration, final RefactoringStatus status, final IProgressMonitor monitor) throws JavaModelException { 1307 Assert.isNotNull(targetRewrite); 1308 Assert.isNotNull(declaration); 1309 Assert.isNotNull(monitor); 1310 final Set handledMethods= new HashSet (); 1311 final Set handledFields= new HashSet (); 1312 final MemberAccessNodeCollector collector= new MemberAccessNodeCollector(fType.getDeclaringType().newSupertypeHierarchy(new SubProgressMonitor(monitor, 1))); 1313 declaration.accept(collector); 1314 modifyAccessToMethodsFromEnclosingInstance(targetRewrite, handledMethods, collector.getMethodInvocations(), declaration, status); 1315 modifyAccessToFieldsFromEnclosingInstance(targetRewrite, handledFields, collector.getFieldAccesses(), declaration, status); 1316 modifyAccessToFieldsFromEnclosingInstance(targetRewrite, handledFields, collector.getSimpleFieldNames(), declaration, status); 1317 } 1318 1319 private void modifyAccessToFieldsFromEnclosingInstance(CompilationUnitRewrite targetRewrite, Set handledFields, FieldAccess[] fieldAccesses, AbstractTypeDeclaration declaration, RefactoringStatus status) { 1320 FieldAccess access= null; 1321 for (int index= 0; index < fieldAccesses.length; index++) { 1322 access= fieldAccesses[index]; 1323 Assert.isNotNull(access.getExpression()); 1324 if (!(access.getExpression() instanceof ThisExpression) || (!(((ThisExpression) access.getExpression()).getQualifier() != null))) 1325 continue; 1326 1327 final IVariableBinding binding= access.resolveFieldBinding(); 1328 if (binding != null) { 1329 targetRewrite.getASTRewrite().replace(access.getExpression(), createAccessExpressionToEnclosingInstanceFieldText(access, binding, declaration), null); 1330 targetRewrite.getImportRemover().registerRemovedNode(access.getExpression()); 1331 } 1332 } 1333 } 1334 1335 private void modifyAccessToFieldsFromEnclosingInstance(CompilationUnitRewrite targetRewrite, Set handledFields, SimpleName[] simpleNames, AbstractTypeDeclaration declaration, RefactoringStatus status) { 1336 IBinding binding= null; 1337 SimpleName simpleName= null; 1338 IVariableBinding variable= null; 1339 for (int index= 0; index < simpleNames.length; index++) { 1340 simpleName= simpleNames[index]; 1341 binding= simpleName.resolveBinding(); 1342 if (binding != null && binding instanceof IVariableBinding && !(simpleName.getParent() instanceof FieldAccess)) { 1343 variable= (IVariableBinding) binding; 1344 final FieldAccess access= simpleName.getAST().newFieldAccess(); 1345 access.setExpression(createAccessExpressionToEnclosingInstanceFieldText(simpleName, variable, declaration)); 1346 access.setName(simpleName.getAST().newSimpleName(simpleName.getIdentifier())); 1347 targetRewrite.getASTRewrite().replace(simpleName, access, null); 1348 targetRewrite.getImportRemover().registerRemovedNode(simpleName); 1349 } 1350 } 1351 } 1352 1353 private void modifyAccessToMethodsFromEnclosingInstance(CompilationUnitRewrite targetRewrite, Set handledMethods, MethodInvocation[] methodInvocations, AbstractTypeDeclaration declaration, RefactoringStatus status) { 1354 IMethodBinding binding= null; 1355 MethodInvocation invocation= null; 1356 for (int index= 0; index < methodInvocations.length; index++) { 1357 invocation= methodInvocations[index]; 1358 binding= invocation.resolveMethodBinding(); 1359 if (binding != null) { 1360 final Expression target= invocation.getExpression(); 1361 if (target == null) { 1362 final Expression expression= createAccessExpressionToEnclosingInstanceFieldText(invocation, binding, declaration); 1363 targetRewrite.getASTRewrite().set(invocation, MethodInvocation.EXPRESSION_PROPERTY, expression, null); 1364 } else { 1365 if (!(invocation.getExpression() instanceof ThisExpression) || !(((ThisExpression) invocation.getExpression()).getQualifier() != null)) 1366 continue; 1367 targetRewrite.getASTRewrite().replace(target, createAccessExpressionToEnclosingInstanceFieldText(invocation, binding, declaration), null); 1368 targetRewrite.getImportRemover().registerRemovedNode(target); 1369 } 1370 } 1371 } 1372 } 1373 1374 private void modifyConstructors(AbstractTypeDeclaration declaration, ASTRewrite rewrite) throws CoreException { 1375 final MethodDeclaration[] declarations= getConstructorDeclarationNodes(declaration); 1376 for (int index= 0; index < declarations.length; index++) { 1377 Assert.isTrue(declarations[index].isConstructor()); 1378 addParameterToConstructor(rewrite, declarations[index]); 1379 setEnclosingInstanceFieldInConstructor(rewrite, declarations[index]); 1380 } 1381 } 1382 1383 private void modifyInterfaceMemberModifiers(final ITypeBinding binding) { 1384 Assert.isNotNull(binding); 1385 ITypeBinding declaring= binding.getDeclaringClass(); 1386 while (declaring != null && !declaring.isInterface()) { 1387 declaring= declaring.getDeclaringClass(); 1388 } 1389 if (declaring != null) { 1390 final ASTNode node= ASTNodes.findDeclaration(binding, fSourceRewrite.getRoot()); 1391 if (node instanceof AbstractTypeDeclaration) { 1392 ModifierRewrite.create(fSourceRewrite.getASTRewrite(), node).setVisibility(Modifier.PUBLIC, null); 1393 } 1394 } 1395 } 1396 1397 public void setCreateInstanceField(boolean create) { 1398 Assert.isTrue(fIsInstanceFieldCreationPossible); 1399 Assert.isTrue(!fIsInstanceFieldCreationMandatory); 1400 fCreateInstanceField= create; 1401 } 1402 1403 private void setEnclosingInstanceFieldInConstructor(ASTRewrite rewrite, MethodDeclaration decl) throws JavaModelException { 1404 final AST ast= decl.getAST(); 1405 final Block body= decl.getBody(); 1406 final List statements= body.statements(); 1407 if (statements.isEmpty()) { 1408 final Assignment assignment= ast.newAssignment(); 1409 assignment.setLeftHandSide(createReadAccessExpressionForEnclosingInstance(ast)); 1410 assignment.setRightHandSide(ast.newSimpleName(getNameForEnclosingInstanceConstructorParameter())); 1411 rewrite.getListRewrite(body, Block.STATEMENTS_PROPERTY).insertFirst(ast.newExpressionStatement(assignment), null); 1412 } else { 1413 final Statement first= (Statement) statements.get(0); 1414 if (first instanceof ConstructorInvocation) { 1415 rewrite.getListRewrite(first, ConstructorInvocation.ARGUMENTS_PROPERTY).insertFirst(ast.newSimpleName(fEnclosingInstanceFieldName), null); 1416 } else { 1417 int index= 0; 1418 if (first instanceof SuperConstructorInvocation) 1419 index++; 1420 final Assignment assignment= ast.newAssignment(); 1421 assignment.setLeftHandSide(createReadAccessExpressionForEnclosingInstance(ast)); 1422 assignment.setRightHandSide(ast.newSimpleName(getNameForEnclosingInstanceConstructorParameter())); 1423 rewrite.getListRewrite(body, Block.STATEMENTS_PROPERTY).insertAt(ast.newExpressionStatement(assignment), index, null); 1424 } 1425 } 1426 } 1427 1428 public void setEnclosingInstanceName(String name) { 1429 Assert.isNotNull(name); 1430 fEnclosingInstanceFieldName= name; 1431 } 1432 1433 public void setMarkInstanceFieldAsFinal(boolean mark) { 1434 fMarkInstanceFieldAsFinal= mark; 1435 } 1436 1437 private void updateConstructorReference(final ClassInstanceCreation creation, final CompilationUnitRewrite targetRewrite, final ICompilationUnit unit, TextEditGroup group) throws JavaModelException { 1438 Assert.isNotNull(creation); 1439 Assert.isNotNull(targetRewrite); 1440 Assert.isNotNull(unit); 1441 final ASTRewrite rewrite= targetRewrite.getASTRewrite(); 1442 if (fCreateInstanceField) 1443 insertExpressionAsParameter(creation, rewrite, unit, group); 1444 final Expression expression= creation.getExpression(); 1445 if (expression != null) { 1446 rewrite.remove(expression, null); 1447 targetRewrite.getImportRemover().registerRemovedNode(expression); 1448 } 1449 } 1450 1451 private void updateConstructorReference(ITypeBinding[] parameters, ASTNode reference, CompilationUnitRewrite targetRewrite, ICompilationUnit cu) throws CoreException { 1452 final TextEditGroup group= targetRewrite.createGroupDescription(RefactoringCoreMessages.MoveInnerToTopRefactoring_update_constructor_reference); 1453 if (reference instanceof SuperConstructorInvocation) 1454 updateConstructorReference((SuperConstructorInvocation) reference, targetRewrite, cu, group); 1455 else if (reference instanceof ClassInstanceCreation) 1456 updateConstructorReference((ClassInstanceCreation) reference, targetRewrite, cu, group); 1457 else if (reference.getParent() instanceof ClassInstanceCreation) 1458 updateConstructorReference((ClassInstanceCreation) reference.getParent(), targetRewrite, cu, group); 1459 else if (reference.getParent() instanceof ParameterizedType && reference.getParent().getParent() instanceof ClassInstanceCreation) 1460 updateConstructorReference(parameters, (ParameterizedType) reference.getParent(), targetRewrite, cu, group); 1461 } 1462 1463 private void updateConstructorReference(ITypeBinding[] parameters, ParameterizedType type, CompilationUnitRewrite targetRewrite, ICompilationUnit cu, TextEditGroup group) throws CoreException { 1464 final ListRewrite rewrite= targetRewrite.getASTRewrite().getListRewrite(type, ParameterizedType.TYPE_ARGUMENTS_PROPERTY); 1465 TypeParameter parameter= null; 1466 for (int index= type.typeArguments().size(); index < parameters.length; index++) { 1467 parameter= targetRewrite.getRoot().getAST().newTypeParameter(); 1468 parameter.setName(targetRewrite.getRoot().getAST().newSimpleName(parameters[index].getName())); 1469 rewrite.insertLast(parameter, group); 1470 } 1471 if (type.getParent() instanceof ClassInstanceCreation) 1472 updateConstructorReference((ClassInstanceCreation) type.getParent(), targetRewrite, cu, group); 1473 } 1474 1475 private void updateConstructorReference(final SuperConstructorInvocation invocation, final CompilationUnitRewrite targetRewrite, final ICompilationUnit unit, TextEditGroup group) throws CoreException { 1476 Assert.isNotNull(invocation); 1477 Assert.isNotNull(targetRewrite); 1478 Assert.isNotNull(unit); 1479 final ASTRewrite rewrite= targetRewrite.getASTRewrite(); 1480 if (fCreateInstanceField) 1481 insertExpressionAsParameter(invocation, rewrite, unit, group); 1482 final Expression expression= invocation.getExpression(); 1483 if (expression != null) { 1484 rewrite.remove(expression, null); 1485 targetRewrite.getImportRemover().registerRemovedNode(expression); 1486 } 1487 } 1488 1489 private boolean updateNameReference(ITypeBinding[] parameters, Name name, CompilationUnitRewrite targetRewrite, TextEditGroup group) { 1490 if (ASTNodes.asString(name).equals(fType.getFullyQualifiedName('.'))) { 1491 targetRewrite.getASTRewrite().replace(name, getNewQualifiedNameNode(parameters, name), group); 1492 targetRewrite.getImportRemover().registerRemovedNode(name); 1493 return true; 1494 } 1495 targetRewrite.getASTRewrite().replace(name, getNewUnqualifiedTypeNode(parameters, name), group); 1496 targetRewrite.getImportRemover().registerRemovedNode(name); 1497 return true; 1498 } 1499 1500 private boolean updateParameterizedTypeReference(ITypeBinding[] parameters, ParameterizedType type, CompilationUnitRewrite targetRewrite, TextEditGroup group) { 1501 if (!(type.getParent() instanceof ClassInstanceCreation)) { 1502 final ListRewrite rewrite= targetRewrite.getASTRewrite().getListRewrite(type, ParameterizedType.TYPE_ARGUMENTS_PROPERTY); 1503 final AST ast= targetRewrite.getRoot().getAST(); 1504 Type simpleType= null; 1505 for (int index= type.typeArguments().size(); index < parameters.length; index++) { 1506 simpleType= ast.newSimpleType(ast.newSimpleName(parameters[index].getName())); 1507 rewrite.insertLast(simpleType, group); 1508 } 1509 } 1510 return true; 1511 } 1512 1513 private boolean updateReference(ITypeBinding[] parameters, ASTNode node, CompilationUnitRewrite rewrite, TextEditGroup group) { 1514 if (node.getLocationInParent() == ParameterizedType.TYPE_PROPERTY) { 1515 updateParameterizedTypeReference(parameters, (ParameterizedType) node.getParent(), rewrite, group); 1516 return updateNameReference(new ITypeBinding[] {}, ((SimpleType) node).getName(), rewrite, group); 1517 } else if (node instanceof QualifiedName) 1518 return updateNameReference(parameters, (QualifiedName) node, rewrite, group); 1519 else if (node instanceof SimpleType) 1520 return updateNameReference(parameters, ((SimpleType) node).getName(), rewrite, group); 1521 else 1522 return false; 1523 } 1524 1525 private void updateReferenceInImport(ImportDeclaration enclosingImport, ASTNode node, CompilationUnitRewrite rewrite) throws CoreException { 1526 final IBinding binding= enclosingImport.resolveBinding(); 1527 if (binding instanceof ITypeBinding) { 1528 final ITypeBinding type= (ITypeBinding) binding; 1529 final ImportRewrite rewriter= rewrite.getImportRewrite(); 1530 if (enclosingImport.isStatic()) { 1531 final String oldImport= ASTNodes.asString(node); 1532 final StringBuffer buffer= new StringBuffer (oldImport); 1533 final String typeName= fType.getDeclaringType().getElementName(); 1534 final int index= buffer.indexOf(typeName); 1535 if (index >= 0) { 1536 buffer.delete(index, index + typeName.length() + 1); 1537 final String newImport= buffer.toString(); 1538 if (enclosingImport.isOnDemand()) { 1539 rewriter.removeStaticImport(oldImport + ".*"); rewriter.addStaticImport(newImport, "*", false); } else { 1542 rewriter.removeStaticImport(oldImport); 1543 final int offset= newImport.lastIndexOf('.'); 1544 if (offset >= 0 && offset < newImport.length() - 1) { 1545 rewriter.addStaticImport(newImport.substring(0, offset), newImport.substring(offset + 1), false); 1546 } 1547 } 1548 } 1549 } else 1550 rewriter.removeImport(type.getQualifiedName()); 1551 } 1552 } 1553 1554 private void updateTypeReference(ITypeBinding[] parameters, ASTNode node, CompilationUnitRewrite rewrite, ICompilationUnit cu) throws CoreException { 1555 ImportDeclaration enclosingImport= (ImportDeclaration) ASTNodes.getParent(node, ImportDeclaration.class); 1556 if (enclosingImport != null) 1557 updateReferenceInImport(enclosingImport, node, rewrite); 1558 else { 1559 final TextEditGroup group= rewrite.createGroupDescription(RefactoringCoreMessages.MoveInnerToTopRefactoring_update_type_reference); 1560 updateReference(parameters, node, rewrite, group); 1561 if (!fType.getPackageFragment().equals(cu.getParent())) { 1562 final String name= fType.getPackageFragment().getElementName() + '.' + fType.getElementName(); 1563 rewrite.getImportRemover().registerAddedImport(name); 1564 rewrite.getImportRewrite().addImport(name); 1565 } 1566 } 1567 } 1568 1569 public RefactoringStatus initialize(final RefactoringArguments arguments) { 1570 if (arguments instanceof JavaRefactoringArguments) { 1571 final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments; 1572 final String handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT); 1573 if (handle != null) { 1574 final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false); 1575 if (element == null || !element.exists() || element.getElementType() != IJavaElement.TYPE) 1576 return createInputFatalStatus(element, IJavaRefactorings.CONVERT_MEMBER_TYPE); 1577 else { 1578 fType= (IType) element; 1579 fCodeGenerationSettings= JavaPreferencesSettings.getCodeGenerationSettings(fType.getJavaProject()); 1580 try { 1581 initialize(); 1582 } catch (JavaModelException exception) { 1583 JavaPlugin.log(exception); 1584 } 1585 } 1586 } else 1587 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT)); 1588 final String fieldName= extended.getAttribute(ATTRIBUTE_FIELD_NAME); 1589 if (fieldName != null && !"".equals(fieldName)) fEnclosingInstanceFieldName= fieldName; 1591 final String parameterName= extended.getAttribute(ATTRIBUTE_PARAMETER_NAME); 1592 if (parameterName != null && !"".equals(parameterName)) fNameForEnclosingInstanceConstructorParameter= parameterName; 1594 final String createField= extended.getAttribute(ATTRIBUTE_FIELD); 1595 if (createField != null) { 1596 fCreateInstanceField= Boolean.valueOf(createField).booleanValue(); 1597 } else 1598 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_FIELD)); 1599 final String markFinal= extended.getAttribute(ATTRIBUTE_FINAL); 1600 if (markFinal != null) { 1601 fMarkInstanceFieldAsFinal= Boolean.valueOf(markFinal).booleanValue(); 1602 } else 1603 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_FINAL)); 1604 final String possible= extended.getAttribute(ATTRIBUTE_POSSIBLE); 1605 if (possible != null) { 1606 fIsInstanceFieldCreationPossible= Boolean.valueOf(possible).booleanValue(); 1607 } else 1608 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_POSSIBLE)); 1609 final String mandatory= extended.getAttribute(ATTRIBUTE_MANDATORY); 1610 if (mandatory != null) 1611 fIsInstanceFieldCreationMandatory= Boolean.valueOf(mandatory).booleanValue(); 1612 else 1613 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_MANDATORY)); 1614 } else 1615 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments); 1616 return new RefactoringStatus(); 1617 } 1618} 1619 | Popular Tags |