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.List ; 20 import java.util.Set ; 21 import java.util.Vector ; 22 23 import org.eclipse.text.edits.MultiTextEdit; 24 import org.eclipse.text.edits.RangeMarker; 25 import org.eclipse.text.edits.TextEdit; 26 27 import org.eclipse.core.runtime.CoreException; 28 import org.eclipse.core.runtime.IProgressMonitor; 29 30 import org.eclipse.core.resources.IFile; 31 32 import org.eclipse.jdt.core.ICompilationUnit; 33 import org.eclipse.jdt.core.IJavaProject; 34 import org.eclipse.jdt.core.IType; 35 import org.eclipse.jdt.core.JavaModelException; 36 import org.eclipse.jdt.core.NamingConventions; 37 import org.eclipse.jdt.core.dom.AST; 38 import org.eclipse.jdt.core.dom.ASTNode; 39 import org.eclipse.jdt.core.dom.ASTVisitor; 40 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; 41 import org.eclipse.jdt.core.dom.Assignment; 42 import org.eclipse.jdt.core.dom.Block; 43 import org.eclipse.jdt.core.dom.BodyDeclaration; 44 import org.eclipse.jdt.core.dom.ClassInstanceCreation; 45 import org.eclipse.jdt.core.dom.CompilationUnit; 46 import org.eclipse.jdt.core.dom.Expression; 47 import org.eclipse.jdt.core.dom.FieldAccess; 48 import org.eclipse.jdt.core.dom.IBinding; 49 import org.eclipse.jdt.core.dom.IMethodBinding; 50 import org.eclipse.jdt.core.dom.ITypeBinding; 51 import org.eclipse.jdt.core.dom.IVariableBinding; 52 import org.eclipse.jdt.core.dom.MethodDeclaration; 53 import org.eclipse.jdt.core.dom.MethodInvocation; 54 import org.eclipse.jdt.core.dom.Modifier; 55 import org.eclipse.jdt.core.dom.Name; 56 import org.eclipse.jdt.core.dom.PostfixExpression; 57 import org.eclipse.jdt.core.dom.PrefixExpression; 58 import org.eclipse.jdt.core.dom.PrimitiveType; 59 import org.eclipse.jdt.core.dom.QualifiedName; 60 import org.eclipse.jdt.core.dom.ReturnStatement; 61 import org.eclipse.jdt.core.dom.SimpleName; 62 import org.eclipse.jdt.core.dom.SingleVariableDeclaration; 63 import org.eclipse.jdt.core.dom.Statement; 64 import org.eclipse.jdt.core.dom.SuperFieldAccess; 65 import org.eclipse.jdt.core.dom.SuperMethodInvocation; 66 import org.eclipse.jdt.core.dom.ThisExpression; 67 import org.eclipse.jdt.core.dom.Type; 68 import org.eclipse.jdt.core.dom.TypeDeclaration; 69 import org.eclipse.jdt.core.dom.VariableDeclaration; 70 import org.eclipse.jdt.core.dom.VariableDeclarationFragment; 71 72 import org.eclipse.jface.text.IRegion; 73 import org.eclipse.jface.text.Region; 74 75 import org.eclipse.jdt.internal.corext.Assert; 76 import org.eclipse.jdt.internal.corext.Corext; 77 import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings; 78 import org.eclipse.jdt.internal.corext.codemanipulation.ImportRewrite; 79 import org.eclipse.jdt.internal.corext.dom.OldASTRewrite; 80 import org.eclipse.jdt.internal.corext.dom.Bindings; 81 import org.eclipse.jdt.internal.corext.dom.HierarchicalASTVisitor; 82 import org.eclipse.jdt.internal.corext.dom.JavaElementMapper; 83 import org.eclipse.jdt.internal.corext.dom.ScopeAnalyzer; 84 import org.eclipse.jdt.internal.corext.refactoring.Checks; 85 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; 86 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext; 87 import org.eclipse.jdt.internal.corext.refactoring.base.RefactoringStatusCodes; 88 import org.eclipse.jdt.internal.corext.refactoring.changes.TextChangeCompatibility; 89 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationStateChange; 90 import org.eclipse.jdt.internal.corext.refactoring.structure.InstanceMethodMover.Method.Delegation; 91 import org.eclipse.jdt.internal.corext.refactoring.structure.InstanceMethodMover.Method.MethodEditSession; 92 import org.eclipse.jdt.internal.corext.refactoring.structure.MoveInstanceMethodRefactoring.INewReceiver; 93 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil; 94 import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager; 95 import org.eclipse.jdt.internal.corext.textmanipulation.TextBuffer; 96 import org.eclipse.jdt.internal.corext.textmanipulation.TextBufferEditor; 97 import org.eclipse.jdt.internal.corext.util.CodeFormatterUtil; 98 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 99 import org.eclipse.jdt.internal.corext.util.JdtFlags; 100 import org.eclipse.jdt.internal.corext.util.Strings; 101 import org.eclipse.ltk.core.refactoring.Change; 102 import org.eclipse.ltk.core.refactoring.RefactoringStatus; 103 import org.eclipse.ltk.core.refactoring.RefactoringStatusContext; 104 import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry; 105 import org.eclipse.ltk.core.refactoring.TextChange; 106 107 class InstanceMethodMover { 108 109 private static interface IParameter { 110 public ITypeBinding getType(); 111 112 public String getName(); 113 } 114 115 private static abstract class NewReceiver implements MoveInstanceMethodRefactoring.INewReceiver { 116 private final IJavaProject fDependentProject; 117 118 private IType fModelClass; 120 121 private NewReceiver(IJavaProject dependentProject, CodeGenerationSettings codeGenSettings) { 122 Assert.isNotNull(dependentProject); 123 Assert.isNotNull(codeGenSettings); 124 125 fDependentProject= dependentProject; 126 } 127 128 public abstract String getName(); 129 130 public ITypeBinding getType() { 131 return getReceiverClass(); 132 } 133 134 public boolean isField() { 135 return false; 136 } 137 138 public boolean isParameter() { 139 return false; 140 } 141 142 protected abstract ITypeBinding getReceiverClass(); 143 144 protected ICompilationUnit getReceiverClassCU() throws JavaModelException { 145 return JavaModelUtil.toWorkingCopy(getReceiverModelClass().getCompilationUnit()); 146 } 147 148 abstract Expression[] getReferencesIn(Method method); 149 150 abstract Expression createReferenceForContext(Method context); 151 152 Change moveMethodToMe(Method method, String newMethodName, String originalReceiverParameterName, boolean inlineDelegator, boolean removeDelegator) throws CoreException { 153 Assert.isNotNull(method); 154 Assert.isNotNull(newMethodName); 155 Assert.isNotNull(originalReceiverParameterName); 156 Assert.isTrue(inlineDelegator || !removeDelegator); 157 Assert.isTrue(Arrays.asList(method.getPossibleNewReceivers()).contains(this)); 158 159 TextChangeManager manager= new TextChangeManager(); 160 addMovedMethodToMyClass(manager, method, newMethodName, originalReceiverParameterName); 161 replaceOriginalMethodBodyWithDelegation(manager, method, newMethodName); 162 163 return getChange(manager); 164 } 165 166 private static Change getChange(TextChangeManager manager) { 167 TextChange[] changes= manager.getAllChanges(); 168 if (changes.length == 1) { 169 return changes[0]; 170 } else { 171 return new DynamicValidationStateChange(RefactoringCoreMessages.getString("InstanceMethodMover.move_method"), changes); } 173 } 174 175 private void replaceOriginalMethodBodyWithDelegation(TextChangeManager manager, Method originalMethod, String newMethodName) throws CoreException { 176 Method.MethodEditSession methodEditSession= originalMethod.createEditSession(); 177 methodEditSession.replaceBodyWithDelegation( 178 specifyDelegationToNewMethod(originalMethod, newMethodName)); 179 TextChange cuChange= manager.get(originalMethod.getDeclaringCU()); 180 TextChangeCompatibility.addTextEdit(cuChange, RefactoringCoreMessages.getString("InstanceMethodMover.replace_with_delegation"), methodEditSession.getEdits()); } 182 183 abstract Method.Delegation specifyDelegationToNewMethod(Method originalMethod, String newMethodName); 184 185 private void addMovedMethodToMyClass(TextChangeManager manager, Method originalMethod, String newMethodName, String originalReceiverParameterName) throws CoreException { 186 List allTypesUsedWithoutQualification= new ArrayList (); 187 TextBufferPortion newMethodText= getNewMethodDeclarationText(originalMethod, newMethodName, originalReceiverParameterName, allTypesUsedWithoutQualification); 188 addNewMethodToMyClass(manager, newMethodText.getUnindentedContentIgnoreFirstLine(), allTypesUsedWithoutQualification); 189 } 190 191 private void addNewMethodToMyClass(TextChangeManager manager, String newMethodText, List allTypesUsedWithoutQualification) throws CoreException { 192 TypeDeclaration myClassDeclaration= getReceiverClassDeclaration(); 193 OldASTRewrite rewrite= new OldASTRewrite(myClassDeclaration); 194 BodyDeclaration newMethodNode= (BodyDeclaration) rewrite.createStringPlaceholder(newMethodText, ASTNode.METHOD_DECLARATION); 195 myClassDeclaration.bodyDeclarations().add(newMethodNode); 196 rewrite.markAsInserted(newMethodNode); 197 198 TextBuffer buffer= TextBuffer.create(getReceiverClassCU().getBuffer().getContents()); 199 MultiTextEdit edit= new MultiTextEdit(); 200 rewrite.rewriteNode(buffer, edit); 201 rewrite.removeModifications(); 202 203 TextChange cuChange= manager.get(getReceiverClassCU()); 204 TextChangeCompatibility.addTextEdit( 205 cuChange, 206 RefactoringCoreMessages.getString("InstanceMethodMover.create_in_receiver"), edit); ImportRewrite importRewrite= createImportRewrite(allTypesUsedWithoutQualification, getReceiverClassCU()); 208 TextChangeCompatibility.addTextEdit( 209 cuChange, 210 RefactoringCoreMessages.getString("InstanceMethodMover.add_imports"), importRewrite.createEdit(buffer.getDocument())); } 212 213 private ImportRewrite createImportRewrite(List types, ICompilationUnit cu) throws CoreException { 214 ImportRewrite importEdit= new ImportRewrite(cu); 215 for(Iterator it= types.iterator(); it.hasNext();) 216 importEdit.addImport((ITypeBinding) it.next()); 217 return importEdit; 218 } 219 220 protected TypeDeclaration getReceiverClassDeclaration() throws JavaModelException { 221 ASTNode result= JavaElementMapper.perform(getReceiverModelClass(), TypeDeclaration.class); 222 Assert.isTrue(result instanceof TypeDeclaration); 223 return (TypeDeclaration) result; 224 } 225 226 private IType getReceiverModelClass() throws JavaModelException { 227 if(fModelClass == null) 228 fModelClass= computeReceiverModelClass(); 229 return fModelClass; 230 } 231 232 private boolean isReceiverModelClassAvailable() throws JavaModelException { 233 if(fModelClass == null) 234 fModelClass= computeReceiverModelClass(); 235 return fModelClass != null; 236 } 237 238 private IType computeReceiverModelClass() throws JavaModelException { 239 return getModelClass(getReceiverClass(), fDependentProject); 240 } 241 242 private TextBufferPortion getNewMethodDeclarationText(Method method, String newMethodName, String originalReceiverParameterName, List allTypesUsed) throws CoreException { 243 Method.MethodEditSession methodEditSession= method.createEditSession(); 244 methodEditSession.changeMethodName(newMethodName); 245 246 methodEditSession.classQualifyNonInstanceMemberReferences(); 247 248 if(method.hasSelfReferences(this)) { 249 methodEditSession.addNewFirstParameter(method.getDeclaringClass(), originalReceiverParameterName); 250 methodEditSession.replaceSelfReferencesWithReferencesToName(originalReceiverParameterName); 251 } 252 253 methodEditSession.replaceNewReceiverReferencesWithSelfReferences(this); 254 transformNonReferenceMentionsIn(methodEditSession); 255 256 TextBufferPortion result= methodEditSession.getEdittedMethodText(); 257 allTypesUsed.addAll(methodEditSession.getAllTypesUsedWithoutQualificationInEdittedMethod()); 258 methodEditSession.clear(); 259 return result; 260 } 261 262 abstract void transformNonReferenceMentionsIn(Method.MethodEditSession methodEditSession); 263 264 IParameter[] getMovedMethodParameterDescriptions(final Method originalMethod, final String originalReceiverParameterName) { 265 Assert.isNotNull(originalMethod); 266 Assert.isNotNull(originalReceiverParameterName); 267 268 IParameter[] originalMethodParams= originalMethod.getParameters(); 269 if(!originalMethod.hasSelfReferences(this)) 270 return originalMethodParams; 271 else { 272 IParameter[] result= new IParameter[1 + originalMethodParams.length]; 273 274 result[0]= new IParameter() { 275 public ITypeBinding getType() { 276 return originalMethod.getDeclaringClass(); 277 } 278 public String getName() { 279 return originalReceiverParameterName; 280 } 281 }; 282 283 for(int i= 0; i < originalMethodParams.length; i++) 284 result[i + 1]= originalMethodParams[i]; 285 286 return result; 287 } 288 } 289 290 public int hashCode() { 291 Assert.isTrue(false, "hashing of NewReceiver unsupported"); return 0; 293 } 294 295 final RefactoringStatus checkMoveOfMethodToMe(Method method, String newMethodName, String originalReceiverParameterName, boolean inlineDelegator, boolean removeDelegator, Object validationContext) throws JavaModelException { 296 Assert.isNotNull(method); 297 Assert.isNotNull(newMethodName); 298 Assert.isNotNull(originalReceiverParameterName); 299 Assert.isTrue(inlineDelegator || ! removeDelegator); 300 301 if( ! isReceiverModelClassAvailable()) 302 return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.getString("InstanceMethodMover.to_local_localunsupported"), null, Corext.getPluginId(), RefactoringStatusCodes.CANNOT_MOVE_TO_LOCAL, null); 304 RefactoringStatus result= new RefactoringStatus(); 305 checkParameterNames(result, method, originalReceiverParameterName); 306 if (result.hasFatalError()) 307 return result; 308 result.merge(Checks.validateModifiesFiles(getFilesToBeModified(method), validationContext)); 309 return result; 310 } 311 312 private void checkParameterNames(RefactoringStatus result, Method method, String originalReceiverParameterName) { 313 for (Iterator iter= method.getMethodDeclaration().parameters().iterator(); iter.hasNext();) { 314 SingleVariableDeclaration param= (SingleVariableDeclaration) iter.next(); 315 if (originalReceiverParameterName.equals(param.getName().getIdentifier())){ 316 RefactoringStatusContext context= JavaStatusContext.create(method.getDeclaringCU(), param); 317 String msg= RefactoringCoreMessages.getFormattedString("InstanceMethodMover.parameter_name_used", new String []{originalReceiverParameterName}); int code= RefactoringStatusCodes.PARAM_NAME_ALREADY_USED; 319 RefactoringStatusEntry entry= new RefactoringStatusEntry(RefactoringStatus.ERROR, msg, context, Corext.getPluginId(), code, null); 320 result.addEntry(entry); 321 return; } 323 } 324 } 325 326 private IFile[] getFilesToBeModified(Method method) throws JavaModelException { 327 IFile file1= getFile(getReceiverClassCU()); 328 IFile file2= getFile(method.getDeclaringCU()); 329 if (file1.equals(file2)) 330 return new IFile[]{file1}; 331 else 332 return new IFile[]{file1, file2}; 333 } 334 335 private static IFile getFile(ICompilationUnit cunit) throws JavaModelException { 336 return ResourceUtil.getFile(cunit); 337 } 338 339 public abstract boolean hasFieldsAccessesOtherThanToMe(SimpleName[] fieldAccesses); 340 } 341 342 private static abstract class VariableNewReceiver extends NewReceiver { 343 VariableNewReceiver(IJavaProject dependentProject, CodeGenerationSettings codeGenSettings) { 344 super(dependentProject, codeGenSettings); 345 } 346 347 protected abstract IVariableBinding getVariable(); 348 349 public IBinding getBinding(){ 350 return getVariable(); 351 } 352 353 protected final RefactoringStatus checkVariableNotWrittenInMethod(Method method) { 354 return new RefactoringStatus(); 356 } 357 358 protected ITypeBinding getReceiverClass() { 359 return getVariable().getType(); 360 } 361 362 public String getName() { 363 return getVariable().getName(); 364 } 365 366 Expression[] getReferencesIn(Method method) { 367 return method.getVariableReferences(getVariable()); 368 } 369 } 370 371 private static class ParameterNewReceiver extends VariableNewReceiver { 372 private final Parameter fParameter; 373 374 ParameterNewReceiver(Parameter parameter, IJavaProject dependentProject, CodeGenerationSettings codeGenSettings) { 375 super(dependentProject, codeGenSettings); 376 Assert.isNotNull(parameter); 377 Assert.isTrue(parameter.getType().isClass()); 378 379 fParameter= parameter; 380 } 381 382 public boolean isParameter() { 383 return true; 384 } 385 386 protected IVariableBinding getVariable() { 387 return fParameter.getBinding(); 388 } 389 390 Expression createReferenceForContext(Method context) { 391 Assert.isTrue(context == fParameter.getMethod()); 392 return fParameter.createReference(); 393 } 394 395 private Parameter getParameter() { 396 return fParameter; 397 } 398 399 public boolean equals(Object o) { 400 if(o == null) 401 return false; 402 if(!getClass().equals(o.getClass())) 403 return false; 404 return getParameter().equals(((ParameterNewReceiver) o).getParameter()); 405 } 406 407 public int hashCode() { 408 return getParameter().hashCode(); 409 } 410 411 protected void transformNonReferenceMentionsIn(MethodEditSession methodEditSession) { 412 methodEditSession.removeParameter(getParameter()); 413 } 414 415 Delegation specifyDelegationToNewMethod(Method originalMethod, String newMethodName) { 416 Method.Delegation delegation= originalMethod.getPotentialDelegationTo(this); 417 delegation.setCalledMethodName(newMethodName); 418 419 boolean hasSelfReferences= originalMethod.hasSelfReferences(this); 420 421 if(hasSelfReferences) 422 delegation.passThisAsArgument(0); 423 424 Parameter[] params= originalMethod.getParameters(); 425 int argumentIndex= hasSelfReferences ? 1 : 0; 426 for(int parameterIndex= 0; parameterIndex < params.length; parameterIndex++) { 427 if(!params[parameterIndex].equals(getParameter())) { 428 delegation.mapParameterToArgument(parameterIndex, argumentIndex); 429 argumentIndex++; 430 } 431 } 432 433 return delegation; 434 } 435 436 public boolean hasFieldsAccessesOtherThanToMe(SimpleName[] fieldAccesses) { 437 return fieldAccesses.length != 0; 438 } 439 } 440 441 private static class FieldNewReceiver extends VariableNewReceiver { 442 private final IVariableBinding fField; 443 444 FieldNewReceiver(IVariableBinding fieldBinding, IJavaProject dependentProject, CodeGenerationSettings codeGenSettings) { 445 super(dependentProject, codeGenSettings); 446 Assert.isNotNull(fieldBinding); 447 Assert.isTrue(fieldBinding.isField()); 448 449 fField= fieldBinding; 450 } 451 452 public boolean isField() { 453 return true; 454 } 455 456 protected IVariableBinding getVariable() { 457 return getField(); 458 } 459 460 private IVariableBinding getField() { 461 return fField; 462 } 463 464 Expression createReferenceForContext(Method context) { 465 Assert.isNotNull(context); 466 return context.createFieldReference(fField); 467 } 468 469 public boolean equals(Object o) { 470 if(o == null) 471 return false; 472 if(!getClass().equals(o.getClass())) 473 return false; 474 return getField().getKey().equals(((FieldNewReceiver) o).getField().getKey()); 475 } 476 477 public int hashCode() { 478 return getField().getKey().hashCode(); 479 } 480 481 482 protected void transformNonReferenceMentionsIn(MethodEditSession methodEditSession) { 483 } 485 486 Delegation specifyDelegationToNewMethod(Method originalMethod, String newMethodName) { 487 Method.Delegation delegation= originalMethod.getPotentialDelegationTo(this); 488 delegation.setCalledMethodName(newMethodName); 489 490 boolean hasSelfReferences= originalMethod.hasSelfReferences(this); 491 492 if(hasSelfReferences) 493 delegation.passThisAsArgument(0); 494 495 int numberOfParams= originalMethod.getParameters().length; 496 for(int parameterIndex= 0; parameterIndex < numberOfParams; parameterIndex++) 497 delegation.mapParameterToArgument( 498 parameterIndex, 499 hasSelfReferences ? 500 parameterIndex + 1 : parameterIndex 501 ); 502 503 return delegation; 504 } 505 506 public boolean hasFieldsAccessesOtherThanToMe(SimpleName[] fieldAccesses) { 507 for (int i = 0; i < fieldAccesses.length; i++) { 509 SimpleName access = fieldAccesses[i]; 510 if (access.resolveBinding() != getField()) { 511 return true; 512 } 513 } 514 return false; 515 } 516 } 517 518 static class Method { 519 static class Delegation { 520 private final NewReceiver fNewReceiver2; 522 private final Method fDelegatingMethod; 523 524 private String fCalledMethodName; 525 private boolean fPassThis; 526 private int fArgumentToPassThisAs; 527 528 private final Vector fArgumentToParameterMap= new Vector (); 529 530 private Delegation(Method delegatingMethod, NewReceiver newReceiver) { 531 Assert.isNotNull(newReceiver); 532 fNewReceiver2= newReceiver; 533 fDelegatingMethod= delegatingMethod; 534 } 535 536 public void setCalledMethodName(String called) { 537 Assert.isNotNull(called); 538 fCalledMethodName= called; 539 } 540 541 public void passThisAsArgument(int argumentIndex) { 542 Assert.isTrue(argumentIndex >= 0); 543 notifyOfNewArgument(argumentIndex); 544 fArgumentToPassThisAs= argumentIndex; 545 fPassThis= true; 546 } 547 548 private void notifyOfNewArgument(int argumentIndex) { 549 if(argumentIndex + 1> fArgumentToParameterMap.size()) 550 fArgumentToParameterMap.setSize(argumentIndex + 1); 551 } 552 553 private int getNumberOfArguments() { 554 return fArgumentToParameterMap.size(); 555 } 556 557 public void mapParameterToArgument(int parameterIndex, int argumentIndex) { 558 Assert.isTrue(parameterIndex >= 0); 559 Assert.isTrue(parameterIndex < fDelegatingMethod.getParameters().length); 560 Assert.isTrue(argumentIndex >= 0); 561 562 notifyOfNewArgument(argumentIndex); 563 fArgumentToParameterMap.set(argumentIndex, new Integer (parameterIndex)); 564 } 565 566 private Method getDelegatingMethod() { 567 return fDelegatingMethod; 568 } 569 570 private MethodInvocation createDelegatingInvocation() { 571 Assert.isTrue(isComplete()); 572 573 MethodInvocation invocation= fDelegatingMethod.getAST().newMethodInvocation(); 574 invocation.setExpression(fNewReceiver2.createReferenceForContext(fDelegatingMethod)); 575 invocation.setName(fDelegatingMethod.getAST().newSimpleName(fCalledMethodName)); 576 577 Parameter[] params= fDelegatingMethod.getParameters(); 578 for(int i= 0; i < getNumberOfArguments(); i++) { 579 if(fPassThis && fArgumentToPassThisAs == i) 580 invocation.arguments().add(fDelegatingMethod.getAST().newThisExpression()); 581 else { 582 Integer parameterIndex= (Integer ) fArgumentToParameterMap.get(i); 583 Assert.isNotNull(parameterIndex); 584 Parameter parameter= params[parameterIndex.intValue()]; 585 invocation.arguments().add(fDelegatingMethod.getAST().newSimpleName(parameter.getName())); 586 } 587 } 588 589 return invocation; 590 } 591 592 private boolean isComplete() { 593 return fCalledMethodName != null 594 && hasAllArguments(); 595 } 596 597 private boolean hasAllArguments() { 598 for(int i= 0; i < getNumberOfArguments(); i++) 599 if(!hasArgument(i)) 600 return false; 601 return true; 602 } 603 604 private boolean hasArgument(int i) { 605 return fArgumentToParameterMap.get(i) != null 606 || fPassThis && fArgumentToPassThisAs == i; 607 608 } 609 } 610 611 static class MethodEditSession { 612 private final Method fMethod; 613 private final OldASTRewrite fRewrite; 614 615 private TypeReferences fTypeReferences; 616 617 private MethodEditSession(Method method) throws JavaModelException { 618 Assert.isNotNull(method); 619 fMethod= method; 620 fRewrite= method.createRewrite(); 621 fTypeReferences= method.getTypeReferences(); 622 } 623 624 public void replaceSelfReferencesWithReferencesToName(String name) { 625 Assert.isNotNull(name); 626 627 replaceExplicitThisReferencesWith(name); 628 replaceImplicitThisInFieldAccessesWith(name); 629 replaceImplicitThisInMethodInvocationsWith(name); 630 } 631 632 private boolean replaceExplicitThisReferencesWith(String name) { 633 ThisExpression[] thisReferences= fMethod.getExplicitThisReferences(); 634 for(int i= 0; i < thisReferences.length; i++) 635 fRewrite.replace(thisReferences[i], thisReferences[i].getAST().newSimpleName(name), null); 636 return thisReferences.length != 0; 637 } 638 639 private boolean replaceImplicitThisInFieldAccessesWith(String name) { 640 SimpleName[] fieldReferences= fMethod.getImplicitThisFieldAccesses(); 641 for(int i= 0; i < fieldReferences.length; i++) { 642 SimpleName fieldName= fieldReferences[i]; 643 FieldAccess replacement= fieldName.getAST().newFieldAccess(); 644 replacement.setExpression(fieldName.getAST().newSimpleName(name)); 645 replacement.setName(fieldName.getAST().newSimpleName(fieldName.getIdentifier())); 646 fRewrite.replace(fieldName, replacement, null); 647 } 648 return fieldReferences.length != 0; 649 } 650 651 private boolean replaceImplicitThisInMethodInvocationsWith(String name) { 652 MethodInvocation[] methodInvocations= fMethod.getImplicitThisMethodInvocations(); 653 for(int i= 0; i < methodInvocations.length; i++) { 654 MethodInvocation original= methodInvocations[i]; 655 Expression newExpression= original.getAST().newSimpleName(name); 656 Assert.isTrue(original.getExpression() == null); 657 original.setExpression(newExpression); 658 fRewrite.markAsInserted(newExpression); 659 } 660 return methodInvocations.length != 0; 661 } 662 663 public void replaceNewReceiverReferencesWithSelfReferences(NewReceiver newReceiver) { 664 Expression[] newReceiverReferences= newReceiver.getReferencesIn(fMethod); 665 for(int i= 0; i < newReceiverReferences.length; i++) 666 replaceExpressionWithSelfReference(newReceiverReferences[i]); 667 } 668 669 private void replaceExpressionWithSelfReference(Expression expression) { 670 Assert.isNotNull(expression); 671 672 ASTNode parent= expression.getParent(); 673 if (parent instanceof MethodInvocation) { 674 MethodInvocation invocation= (MethodInvocation) parent; 675 if(expression.equals(invocation.getExpression())) 676 replaceReceiverWithImplicitThis(invocation); 677 else if (invocation.arguments().contains(expression)) 678 replaceExpressionWithExplicitThis(expression); 679 else 680 Assert.isTrue(false, "expression should be an expression for which, syntactically, \"this\" could by substituted, so not the name in a method invocation."); } else if (parent instanceof FieldAccess) { 682 FieldAccess fieldAccess= (FieldAccess) parent; 683 if (fieldAccess.getExpression() instanceof ThisExpression) { 684 Assert.isTrue(expression.equals(fieldAccess.getName()), "expression should syntactically be substitutable by \"this\""); replaceExpressionWithSelfReference(fieldAccess); } else { 687 Assert.isTrue(expression.equals(fieldAccess.getExpression()), "expression should be an expression for which, syntactically, \"this\" could by substituted, so not the field name in a field access."); replaceReceiverWithImplicitThis(fieldAccess); 689 } 690 } else if (parent instanceof QualifiedName) { 691 QualifiedName qualifiedName= (QualifiedName) parent; 692 Assert.isTrue(isQualifiedNameUsedAsFieldAccessOnObject(qualifiedName, expression), "expression should be an expression for which, syntactically, \"this\" could by substituted."); replaceReceiverWithImplicitThis(qualifiedName); 694 } else 695 replaceExpressionWithExplicitThis(expression); 696 } 697 698 private void replaceReceiverWithImplicitThis(MethodInvocation invocation) { 699 fRewrite.remove(invocation.getExpression(), null); 700 } 701 702 private void replaceReceiverWithImplicitThis(FieldAccess fieldAccess) { 703 fRewrite.replace(fieldAccess, fRewrite.createCopyTarget(fieldAccess.getName()), null); 704 } 705 706 709 private void replaceReceiverWithImplicitThis(QualifiedName fieldAccess) { 710 Assert.isTrue(isFieldAccess(fieldAccess)); 711 fRewrite.replace(fieldAccess, fRewrite.createCopyTarget(fieldAccess.getName()), null); 712 } 713 714 private void replaceExpressionWithExplicitThis(Expression expression) { 715 fRewrite.replace(expression, expression.getAST().newThisExpression(), null); 716 } 717 718 private static boolean isQualifiedNameUsedAsFieldAccessOnObject(QualifiedName fieldAccess, Expression object) { 719 return object.equals(fieldAccess.getQualifier()) && isFieldAccess(fieldAccess); 720 } 721 722 private static boolean isFieldAccess(QualifiedName qName) { 723 IBinding binding= qName.resolveBinding(); 724 Assert.isNotNull(binding); 726 return binding instanceof IVariableBinding && ((IVariableBinding) binding).isField(); 727 } 728 729 public void classQualifyNonInstanceMemberReferences() { 730 Name[] references= fMethod.findOutermostNonRightHandDotOperandNamesInBody(); 731 for(int i= 0; i < references.length; i++) { 732 SimpleName leftMost= getLeftmost(references[i]); 733 if(isNonInstanceMemberReference(leftMost)) 734 classQualify(leftMost); 735 } 736 } 737 738 private boolean isNonInstanceMemberReference(SimpleName name) { 739 if (name.getParent() instanceof ClassInstanceCreation) 740 return false; 741 742 IBinding binding= name.resolveBinding(); 743 if(binding instanceof ITypeBinding) 744 return !((ITypeBinding) binding).isLocal(); 745 if(binding instanceof IMethodBinding) 746 return Modifier.isStatic(((IMethodBinding) binding).getModifiers()); 747 if(binding instanceof IVariableBinding) 748 return Modifier.isStatic(((IVariableBinding) binding).getModifiers()); 749 return false; 750 } 751 752 private void classQualify(SimpleName name) { 753 IBinding nameBinding= name.resolveBinding(); 754 ITypeBinding declaring= getDeclaringClassIfMember(nameBinding); 755 if(declaring == null) 756 return; 757 758 fRewrite.replace( 759 name, 760 name.getAST().newQualifiedName( 761 getClassNameQualifiedToTopLevel(declaring, name.getAST()), 762 (SimpleName) fRewrite.createCopyTarget(name)), null); 763 764 fTypeReferences.addOneReference(getTopLevel(declaring)); 765 if(nameBinding instanceof ITypeBinding) 766 fTypeReferences.removeOneReference((ITypeBinding) nameBinding); 767 } 768 769 private static ITypeBinding getDeclaringClassIfMember(IBinding binding) { 770 if(binding instanceof IMethodBinding) 771 return ((IMethodBinding) binding).getDeclaringClass(); 772 773 if(binding instanceof IVariableBinding) 774 return ((IVariableBinding) binding).getDeclaringClass(); 775 776 if(binding instanceof ITypeBinding) 777 return ((ITypeBinding) binding).getDeclaringClass(); 778 779 return null; 780 } 781 782 private static Name getClassNameQualifiedToTopLevel(ITypeBinding clazz, AST ast) { 783 Assert.isTrue(!clazz.isAnonymous()); 784 785 SimpleName clazzName= ast.newSimpleName(clazz.getName()); 786 if(isTopLevel(clazz)) 787 return clazzName; 788 789 return ast.newQualifiedName(getClassNameQualifiedToTopLevel(clazz.getDeclaringClass(), ast), clazzName); 790 } 791 792 private static ITypeBinding getTopLevel(ITypeBinding clazz) { 793 Assert.isTrue(!clazz.isAnonymous()); 794 795 ITypeBinding current= clazz; 796 while(!isTopLevel(current)) 797 current= current.getDeclaringClass(); 798 return current; 799 } 800 801 804 private static boolean isTopLevel(ITypeBinding clazz) { 805 Assert.isNotNull(clazz); 806 Assert.isTrue(!clazz.isAnonymous()); 807 ITypeBinding declaring= clazz.getDeclaringClass(); 808 return clazz.isLocal() || declaring == null || declaring.isAnonymous(); 809 } 810 811 public void changeMethodName(String newName) { 812 Assert.isNotNull(newName); 813 SimpleName originalName= fMethod.getNameNode(); 814 if (! originalName.getIdentifier().equals(newName)) 815 fRewrite.replace(originalName, originalName.getAST().newSimpleName(newName), null); 816 } 817 818 public void addNewFirstParameter(ITypeBinding parameterType, String parameterName) { 819 SingleVariableDeclaration newDecl= fMethod.addNewFirstParameter(parameterType, parameterName); 820 fRewrite.markAsInserted(newDecl); 821 if(parameterType.isClass() || parameterType.isInterface()) { 822 Assert.isNotNull(fTypeReferences, "this session has already been destroyed."); fTypeReferences.addOneReference(parameterType); 824 } 825 } 826 827 public void removeParameter(Parameter parameter) { 828 fRewrite.remove(fMethod.getParameterDeclaration(parameter), null); 829 ITypeBinding parameterType= parameter.getType(); 830 if(parameterType.isClass() || parameterType.isInterface()) { 831 Assert.isNotNull(fTypeReferences, "this session has already been destroyed."); fTypeReferences.removeOneReference(parameterType); 833 } 834 } 835 836 private Block replaceBody() { 837 Block originalBody= fMethod.getBody(); 838 Block newBody= originalBody.getAST().newBlock(); 839 fRewrite.replace(originalBody, newBody, null); 840 return newBody; 841 } 842 843 public void replaceBodyWithDelegation(Delegation delegation) { 844 Assert.isTrue(delegation.getDelegatingMethod() == fMethod); 845 Block newBody= replaceBody(); 846 List statements= newBody.statements(); 847 848 MethodInvocation delegatingInvocation= delegation.createDelegatingInvocation(); 849 850 Statement delegatingStatement= 851 fMethod.hasVoidReturnType() ? 852 createExpressionStatement(delegatingInvocation) 853 : 854 createReturnStatement(delegatingInvocation); 855 statements.add(delegatingStatement); 856 } 857 858 private Statement createReturnStatement(Expression expression) { 859 ReturnStatement returnStatement= expression.getAST().newReturnStatement(); 860 returnStatement.setExpression(expression); 861 return returnStatement; 862 } 863 864 private Statement createExpressionStatement(Expression expression) { 865 return expression.getAST().newExpressionStatement(expression); 866 } 867 868 public TextBufferPortion getEdittedMethodText() throws CoreException { 869 TextBuffer cuBuffer= fMethod.createDeclaringCUBuffer(); 870 871 MultiTextEdit dummy= getEdits(cuBuffer); 872 873 IRegion range= fMethod.createTextRange(); 874 RangeMarker rangeMarker= new RangeMarker(range.getOffset(), range.getLength()); 875 TextEdit[] edits= dummy.removeChildren(); 876 for (int i= 0; i < edits.length; i++) 877 rangeMarker.addChild(edits[i]); 878 879 MultiTextEdit allEdits= new MultiTextEdit(); 880 allEdits.addChild(rangeMarker); 881 882 TextBufferEditor editor= new TextBufferEditor(cuBuffer); 883 editor.add(allEdits); 884 editor.performEdits(null); 885 886 return new TextBufferPortion(cuBuffer, rangeMarker); 887 } 888 889 public MultiTextEdit getEdits() throws JavaModelException { 890 return getEdits(fMethod.createDeclaringCUBuffer()); 891 } 892 893 private MultiTextEdit getEdits(TextBuffer buffer) { 894 MultiTextEdit rootEdit= new MultiTextEdit(); 895 fRewrite.rewriteNode(buffer, rootEdit); 896 return rootEdit; 897 } 898 899 public Collection getAllTypesUsedWithoutQualificationInEdittedMethod() { 900 Assert.isNotNull(fTypeReferences, "this session has already been destroyed."); return fTypeReferences.getTypesReferencedWithoutQualification(); 902 } 903 904 public void clear() { 905 fRewrite.removeModifications(); 906 fTypeReferences= fMethod.getTypeReferences(); 907 } 908 909 public void destroy() { 910 fRewrite.removeModifications(); 911 fTypeReferences= null; 912 } 913 } 914 915 private static class TypeReferences extends HierarchicalASTVisitor { 916 private HashMap fTypeKeysToUsageCounts= new HashMap (); 917 private HashMap fTypeKeysToATypeBinding= new HashMap (); 918 919 public Collection getTypesReferencedWithoutQualification() { 920 return fTypeKeysToATypeBinding.values(); 921 } 922 923 public int getNumberOfUnqualifiedReferencesTo(ITypeBinding classOrInterface) { 924 Assert.isTrue(classOrInterface.isClass() || classOrInterface.isInterface()); 925 926 Integer references= getValueFor(classOrInterface); 927 if(references == null) 928 return 0; 929 return references.intValue(); 930 } 931 932 public void addAllReferences(ASTNode tree) { 933 tree.accept(this); 934 } 935 936 public void addOneReference(ITypeBinding classOrInterface) { 937 Assert.isTrue(classOrInterface.isClass() || classOrInterface.isInterface()); 938 registerReference(classOrInterface); 939 } 940 941 public void removeOneReference(ITypeBinding classOrInterface) { 942 Assert.isTrue(classOrInterface.isClass() || classOrInterface.isInterface()); 943 944 Integer value= getValueFor(classOrInterface); 945 Assert.isTrue(value != null, "invalid argument"); 947 int currentReferences= value.intValue(); 948 Assert.isTrue(currentReferences > 0); 949 950 if(currentReferences == 1) 951 unmap(classOrInterface); 952 else 953 map( 954 classOrInterface, 955 new Integer (currentReferences - 1) 956 ); 957 } 958 959 private void registerReference(ITypeBinding type) { 960 Integer referencesSoFar= (Integer ) fTypeKeysToUsageCounts.get(type.getKey()); 961 map( 962 type, 963 referencesSoFar == null ? 964 new Integer (1) 965 : 966 new Integer (referencesSoFar.intValue() + 1) 967 ); 968 } 969 970 private void map(ITypeBinding binding, Integer value) { 971 fTypeKeysToUsageCounts.put(binding.getKey(), value); 972 fTypeKeysToATypeBinding.put(binding.getKey(), binding); 973 } 974 975 private void unmap(ITypeBinding binding) { 976 fTypeKeysToUsageCounts.remove(binding.getKey()); 977 fTypeKeysToATypeBinding.remove(binding.getKey()); 978 } 979 980 private Integer getValueFor(ITypeBinding binding) { 981 return (Integer ) fTypeKeysToUsageCounts.get(binding.getKey()); 982 } 983 984 public boolean visit(Name name) { 985 SimpleName leftmost= getLeftmost(name); 986 987 IBinding binding= leftmost.resolveBinding(); 988 if(binding instanceof ITypeBinding) 989 registerReference((ITypeBinding) binding); 990 991 return false; 992 } 993 } 994 995 private final ICompilationUnit fDeclaringCU; 996 private final MethodDeclaration fMethodNode; 997 private final ITypeBinding fDeclaringClass; 998 private final CodeGenerationSettings fCodeGenSettings; 999 1000 private NewReceiver[] fPossibleNewReceivers; 1002 1003 static Method create(MethodDeclaration declaration, ICompilationUnit declaringCU, CodeGenerationSettings codeGenSettings) { 1004 ITypeBinding declaringClass= getDeclaringClassBinding(declaration); 1005 if (declaringClass == null) return null; 1006 return new Method(declaration, declaringCU, codeGenSettings, declaringClass); 1007 } 1008 1009 private Method(MethodDeclaration declaration, ICompilationUnit declaringCU, CodeGenerationSettings codeGenSettings, ITypeBinding declaringClass) { 1010 Assert.isNotNull(declaringCU); 1011 Assert.isTrue(declaringCU.exists()); 1012 Assert.isNotNull(declaration); 1013 Assert.isNotNull(codeGenSettings); 1014 Assert.isNotNull(declaringClass); 1015 1016 fDeclaringCU= declaringCU; 1017 fMethodNode= declaration; 1018 1019 fDeclaringClass= declaringClass; 1020 fCodeGenSettings= codeGenSettings; 1021 } 1022 1023 public Expression createFieldReference(IVariableBinding field) { 1024 Assert.isTrue(field.isField()); 1025 1028 if(parameterShadows(field)) 1029 return createThisFieldAccess(field); 1030 1031 return createFieldName(field); 1032 } 1033 1034 private boolean parameterShadows(IVariableBinding field) { 1035 Parameter[] params= getParameters(); 1036 for(int i= 0; i < params.length; i++) 1037 if(params[i].getName().equals(field.getName())) 1038 return true; 1039 return false; 1040 } 1041 1042 private Expression createThisFieldAccess(IVariableBinding field) { 1043 FieldAccess access= fMethodNode.getAST().newFieldAccess(); 1044 access.setExpression(fMethodNode.getAST().newThisExpression()); 1045 access.setName(createFieldName(field)); 1046 return access; 1047 } 1048 1049 private SimpleName createFieldName(IVariableBinding field) { 1050 return fMethodNode.getAST().newSimpleName(field.getName()); 1051 } 1052 1053 private Block getBody() { 1054 Block body= fMethodNode.getBody(); 1055 Assert.isNotNull(body); 1056 return body; 1057 } 1058 1059 MethodDeclaration getMethodDeclaration(){ 1060 return fMethodNode; 1061 } 1062 1063 public SingleVariableDeclaration addNewFirstParameter(ITypeBinding parameterType, String parameterName) { 1064 Assert.isNotNull(parameterType); 1065 Assert.isNotNull(parameterName); 1066 Assert.isTrue(parameterType.isClass() || parameterType.isInterface()); 1067 1068 SingleVariableDeclaration newDecl= fMethodNode.getAST().newSingleVariableDeclaration(); 1069 newDecl.setType(fMethodNode.getAST().newSimpleType(fMethodNode.getAST().newSimpleName(parameterType.getName()))); 1070 newDecl.setName(fMethodNode.getAST().newSimpleName(parameterName)); 1071 1072 fMethodNode.parameters().add(0, newDecl); 1073 return newDecl; 1074 } 1075 1076 public Delegation getPotentialDelegationTo(NewReceiver newReceiver) { 1077 Assert.isNotNull(newReceiver); 1078 Assert.isTrue(Arrays.asList(getPossibleNewReceivers()).contains(newReceiver)); 1079 return new Delegation(this, newReceiver); 1080 } 1081 1082 private SimpleName getNameNode() { 1083 return fMethodNode.getName(); 1084 } 1085 1086 1090 Name[] getVariableReferences(final IVariableBinding variable) { 1091 Assert.isNotNull(variable); 1092 1093 final List result= new ArrayList (); 1094 fMethodNode.accept( 1095 new HierarchicalASTVisitor() { 1096 public boolean visit(Name name) { 1097 Assert.isNotNull(name); 1098 IBinding binding= name.resolveBinding(); 1099 if(binding == null) 1101 return true; 1102 if(!(binding instanceof IVariableBinding)) 1103 return true; 1104 1105 if( areSameVariable(variable, (IVariableBinding) binding) 1106 && !isDeclaredNamePartOfDeclaration(name) 1107 ) { 1108 result.add(name); 1109 return false; 1110 } 1111 1112 return true; 1113 } 1114 1115 private boolean isDeclaredNamePartOfDeclaration(Name name) { 1116 ASTNode parent= name.getParent(); 1117 if(!(parent instanceof VariableDeclaration)) 1118 return false; 1119 if(parent instanceof VariableDeclarationFragment) { 1120 VariableDeclarationFragment fragment= (VariableDeclarationFragment) parent; 1121 return name.equals(fragment.getName()); 1122 } else if(parent instanceof SingleVariableDeclaration) { 1123 SingleVariableDeclaration decl= (SingleVariableDeclaration) parent; 1124 return name.equals(decl.getName()); 1125 } 1126 Assert.isTrue(false); return false; 1127 } 1128 1129 private boolean areSameVariable(IVariableBinding one, IVariableBinding other) { 1130 1135 return one.equals(other); 1136 } 1137 } 1138 ); 1139 return (Name[]) result.toArray(new Name[result.size()]); 1140 } 1141 1142 private static ITypeBinding getDeclaringClassBinding(MethodDeclaration decl) { 1143 Assert.isNotNull(decl); 1144 1145 IMethodBinding binding= decl.resolveBinding(); 1146 if (binding == null) 1147 return null; 1148 return binding.getDeclaringClass(); 1149 } 1150 1151 public String getName() { 1152 return fMethodNode.getName().getIdentifier(); 1153 } 1154 1155 private ITypeBinding[] getParameterTypes() { 1156 Parameter[] params= getParameters(); 1157 1158 ITypeBinding[] types= new ITypeBinding[params.length]; 1159 for(int i= 0; i < params.length; i++) 1160 types[i]= params[i].getType(); 1161 return types; 1162 } 1163 1164 public Parameter[] getParameters() { 1165 List parameters= new ArrayList (); 1166 for(Iterator it= fMethodNode.parameters().iterator(); it.hasNext();) { 1167 IVariableBinding paramBinding= ((SingleVariableDeclaration) it.next()).resolveBinding(); 1168 if (paramBinding == null) 1169 return new Parameter[0]; 1171 parameters.add(new Parameter(this, paramBinding)); 1172 } 1173 return (Parameter[]) parameters.toArray(new Parameter[parameters.size()]); 1174 } 1175 1176 public ITypeBinding getDeclaringClass() { 1177 return fDeclaringClass; 1178 } 1179 1180 public ICompilationUnit getDeclaringCU() { 1181 return fDeclaringCU; 1182 } 1183 1184 private IJavaProject getProject() { 1185 return getDeclaringCU().getJavaProject(); 1186 } 1187 1188 public RefactoringStatus checkCanBeMoved() { 1189 if(isStatic()) 1190 return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.getString("InstanceMethodMover.no_static_methods"), null, Corext.getPluginId(), RefactoringStatusCodes.CANNOT_MOVE_STATIC, null); if(isAbstract()) 1192 return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.getString("InstanceMethodMover.single_implementation"), null, Corext.getPluginId(), RefactoringStatusCodes.SELECT_METHOD_IMPLEMENTATION, null); if(isNative()) 1194 return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.getString("InstanceMethodMover.no_native_methods"), null, Corext.getPluginId(), RefactoringStatusCodes.CANNOT_MOVE_NATIVE, null); if(isSynchronized()) 1196 return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.getString("InstanceMethodMover.no_synchronized_methods"), null, Corext.getPluginId(), RefactoringStatusCodes.CANNOT_MOVE_SYNCHRONIZED, null); if(isConstructor()) 1198 return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.getString("InstanceMethodMover.no_constructors"), null, Corext.getPluginId(), RefactoringStatusCodes.CANNOT_MOVE_CONSTRUCTOR, null); if(hasSuperReferences()) 1200 return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.getString("InstanceMethodMover.uses_super"), null, Corext.getPluginId(), RefactoringStatusCodes.SUPER_REFERENCES_NOT_ALLOWED, null); if(refersToEnclosingInstances()) 1202 return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.getString("InstanceMethodMover.refers_enclosing_instances"), null, Corext.getPluginId(), RefactoringStatusCodes.ENCLOSING_INSTANCE_REFERENCES_NOT_ALLOWED, null); if(mayBeDirectlyRecursive()) 1204 return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.getString("InstanceMethodMover.potentially_recursive"), null, Corext.getPluginId(), RefactoringStatusCodes.CANNOT_MOVE_RECURSIVE, null); 1206 if (getPossibleNewReceivers().length == 0) 1207 return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.getString("InstanceMethodMover.cannot_be_moved"), null, Corext.getPluginId(), RefactoringStatusCodes.NO_NEW_RECEIVERS, null); return new RefactoringStatus(); 1209 } 1210 1211 private boolean hasSuperReferences() { 1212 class SuperReferenceChecker extends ASTVisitor { 1213 private boolean fSuperReferencesFound= false; 1214 1215 public boolean superReferencesFound() { 1216 return fSuperReferencesFound; 1217 } 1218 1219 public boolean visit(AnonymousClassDeclaration node) { 1220 return false; } 1222 1223 public boolean visit(TypeDeclaration node) { 1224 return false; } 1226 1227 public boolean visit(SuperFieldAccess node) { 1228 fSuperReferencesFound= true; 1229 return false; 1230 } 1231 1232 public boolean visit(SuperMethodInvocation node) { 1233 fSuperReferencesFound= true; 1234 return false; 1235 } 1236 } 1237 1238 SuperReferenceChecker checker= new SuperReferenceChecker(); 1239 fMethodNode.accept(checker); 1240 return checker.superReferencesFound(); 1241 } 1242 1243 private boolean isStatic() { 1244 return Modifier.isStatic(getModifiers()); 1245 } 1246 1247 private boolean isNative() { 1248 return Modifier.isNative(getModifiers()); 1249 } 1250 1251 private boolean isConstructor() { 1252 IMethodBinding binding= fMethodNode.resolveBinding(); 1253 Assert.isNotNull(binding); 1255 return binding.isConstructor(); 1256 } 1257 1258 private boolean isSynchronized() { 1259 return Modifier.isSynchronized(getModifiers()); 1260 } 1261 1262 private boolean isAbstract() { 1263 return getDeclaringClass().isInterface() || Modifier.isAbstract(getModifiers()); 1264 } 1265 1266 private boolean refersToEnclosingInstances() { 1267 class EnclosingInstanceReferenceChecker extends ASTVisitor { 1268 private boolean fEnclosingInstanceReferencesFound= false; 1269 1270 public boolean enclosingInstanceReferencesFound() { 1271 return fEnclosingInstanceReferencesFound; 1272 } 1273 1274 public boolean visit(ThisExpression node) { 1275 if(node.getQualifier() != null) 1276 fEnclosingInstanceReferencesFound= true; 1277 return false; 1278 } 1279 } 1280 1281 EnclosingInstanceReferenceChecker checker= new EnclosingInstanceReferenceChecker(); 1282 fMethodNode.accept(checker); 1283 return checker.enclosingInstanceReferencesFound(); 1284 } 1285 1286 private boolean mayBeDirectlyRecursive() { 1287 Assert.isTrue(!hasSuperReferences()); 1288 1289 class RecursionChecker extends ASTVisitor { 1290 private boolean fMethodMayBeRecursive= false; 1291 1292 public boolean mayBeRecursive() { 1293 fMethodNode.accept(this); 1294 return fMethodMayBeRecursive; 1295 } 1296 1297 public boolean visit(MethodInvocation invocation) { 1298 IMethodBinding binding= invocation.resolveMethodBinding(); 1299 if (binding == null){ 1300 fMethodMayBeRecursive= true; 1301 return false; 1302 } 1303 1304 if(!isSelfSend(invocation)) 1305 return true; 1306 1307 if(hasSameSignature(binding)){ 1308 fMethodMayBeRecursive= true; 1309 return false; 1310 } 1311 1312 return true; 1313 } 1314 1315 private boolean hasSameSignature(IMethodBinding other) { 1316 if(!getName().equals(other.getName())) 1317 return false; 1318 return hasSameParameterTypes(other); 1319 } 1320 1321 private boolean hasSameParameterTypes(IMethodBinding other) { 1322 ITypeBinding[] mine= getParameterTypes(); 1323 ITypeBinding[] others= other.getParameterTypes(); 1324 if(mine.length != others.length) 1325 return false; 1326 1327 for(int i= 0; i < mine.length; i++) 1328 if(!mine[i].getKey().equals(others[i].getKey())) 1329 return false; 1330 1331 return true; 1332 } 1333 1334 private boolean isSelfSend(MethodInvocation invocation) { 1335 if(isStatic(invocation)) 1336 return false; 1337 1338 Expression receiver= invocation.getExpression(); 1339 return receiver == null 1340 || receiver instanceof ThisExpression; 1341 } 1342 1343 private boolean isStatic(MethodInvocation invocation) { 1344 return JdtFlags.isStatic(invocation.resolveMethodBinding()); 1345 } 1346 } 1347 1348 RecursionChecker checker= new RecursionChecker(); 1349 return checker.mayBeRecursive(); 1350 } 1351 1352 private int getModifiers() { 1353 return getBinding().getModifiers(); 1354 } 1355 1356 public NewReceiver[] getPossibleNewReceivers() { 1357 if(fPossibleNewReceivers == null) 1358 fPossibleNewReceivers= findPossibleNewReceivers(); 1359 return fPossibleNewReceivers; 1360 } 1361 1362 private NewReceiver[] findPossibleNewReceivers() { 1363 List newReceivers= new ArrayList (); 1364 1365 addPossibleParameterNewReceivers(newReceivers); 1366 addPossibleFieldNewReceivers(newReceivers); 1367 1368 return (NewReceiver[]) newReceivers.toArray(new NewReceiver[newReceivers.size()]); 1369 } 1370 1371 private static boolean canAddAsPossibleNewReceiver(ITypeBinding type){ 1372 return type.isClass() && type.isFromSource(); 1373 } 1374 1375 private void addPossibleParameterNewReceivers(List target) { 1376 Assert.isNotNull(target); 1377 1378 Parameter[] parameters= getParameters(); 1379 for(int i= 0; i < parameters.length; i++) { 1380 if(canAddAsPossibleNewReceiver(parameters[i].getType())) 1381 target.add(new ParameterNewReceiver(parameters[i], getProject(), fCodeGenSettings)); 1382 } 1383 } 1384 1385 private void addPossibleFieldNewReceivers(List target) { 1386 Assert.isNotNull(target); 1387 IVariableBinding[] fields= findFieldsOfSelfReadButNotWritten(); 1388 for(int i= 0; i < fields.length; i++) { 1389 if (canAddAsPossibleNewReceiver(fields[i].getType())) 1390 target.add(new FieldNewReceiver(fields[i], getProject(), fCodeGenSettings)); 1391 } 1392 } 1393 1394 private IVariableBinding[] findFieldsOfSelfReadButNotWritten() { 1395 Collection result= keepFieldsNotWritten(findReferencedFieldsOfSelf()); 1396 return (IVariableBinding[]) result.toArray(new IVariableBinding[result.size()]); 1397 } 1398 1399 1403 private Set getKeysOfAllWrittenFields() { 1404 final HashSet writtenFieldKeys= new HashSet (); 1405 1406 fMethodNode.accept( 1407 new ASTVisitor() { 1408 public boolean visit(Assignment assignment) { 1409 reportExpressionModified(assignment.getLeftHandSide()); 1410 return true; 1411 } 1412 1413 public boolean visit(PostfixExpression node) { 1414 reportExpressionModified(node.getOperand()); 1415 return true; 1416 } 1417 1418 public boolean visit(PrefixExpression node) { 1419 reportExpressionModified(node.getOperand()); 1420 return false; 1421 } 1422 1423 private void reportExpressionModified(Expression exp) { 1424 IVariableBinding field 1425 = getFieldBindingIfField(exp); 1426 if(field != null) 1427 reportFieldWritten(field); 1428 } 1429 1430 private void reportFieldWritten(IVariableBinding field) { 1431 Assert.isTrue(field.isField()); 1432 writtenFieldKeys.add(field.getKey()); 1433 } 1434 1435 private IVariableBinding getFieldBindingIfField(Expression exp) { 1436 if(exp instanceof FieldAccess) 1437 return (IVariableBinding) ((FieldAccess) exp).getName().resolveBinding(); 1438 if(exp instanceof Name) { 1439 IBinding binding= ((Name) exp).resolveBinding(); 1440 if(binding instanceof IVariableBinding) { 1441 IVariableBinding variable= (IVariableBinding) binding; 1442 if(variable.isField()) 1443 return variable; 1444 } 1445 } 1446 return null; 1447 } 1448 } 1449 ); 1450 return writtenFieldKeys; 1451 } 1452 1453 private Collection keepFieldsNotWritten(Collection fields) { 1454 Set writtenFieldKeys= getKeysOfAllWrittenFields(); 1455 1456 Collection result= new ArrayList (); 1457 for(Iterator it= fields.iterator(); it.hasNext();) { 1458 IVariableBinding field= (IVariableBinding) it.next(); 1459 Assert.isTrue(field.isField()); 1460 if(!writtenFieldKeys.contains(field.getKey())) 1461 result.add(field); 1462 } 1463 return result; 1464 } 1465 1466 private Collection findReferencedFieldsOfSelf() { 1467 final Set fieldKeys= new HashSet (); 1468 final List result= new ArrayList (); 1469 1470 fMethodNode.accept( 1471 new ASTVisitor() { 1472 public boolean visit(FieldAccess node) { 1473 if(node.getExpression() instanceof ThisExpression) { 1474 IVariableBinding field= (IVariableBinding) node.getName().resolveBinding(); 1475 if(field != null) 1476 fieldFound(field); 1477 } 1478 return true; 1479 } 1480 1481 public boolean visit(SimpleName name) { 1482 IBinding binding= name.resolveBinding(); 1483 if(binding != null) 1484 if(isImplicitThisFieldAccess(name)) 1485 fieldFound((IVariableBinding) binding); 1486 return false; 1487 } 1488 1489 private void fieldFound(IVariableBinding field) { 1490 Assert.isTrue(field.isField()); 1491 if(!fieldKeys.contains(field.getKey())) { 1492 fieldKeys.add(field.getKey()); 1493 result.add(field); 1494 } 1495 } 1496 } 1497 ); 1498 return result; 1499 } 1500 1501 private TextBuffer createDeclaringCUBuffer() throws JavaModelException { 1502 return TextBuffer.create(getDeclaringCU().getBuffer().getContents()); 1503 } 1504 1505 private IRegion createTextRange() { 1506 return new Region(fMethodNode.getStartPosition(), fMethodNode.getLength()); 1507 } 1508 1509 private OldASTRewrite createRewrite() { 1510 return new OldASTRewrite(fMethodNode); 1511 } 1512 1513 public MethodEditSession createEditSession() throws JavaModelException { 1514 return new MethodEditSession(this); 1515 } 1516 1517 private ThisExpression[] getExplicitThisReferences() { 1518 final List result= new ArrayList (); 1519 fMethodNode.accept( 1520 new ASTVisitor() { 1521 public boolean visit(ThisExpression node) { 1522 result.add(node); 1523 return false; 1524 } 1525 } 1526 ); 1527 return (ThisExpression[]) result.toArray(new ThisExpression[result.size()]); 1528 } 1529 1530 private MethodInvocation[] getImplicitThisMethodInvocations() { 1531 final List result= new ArrayList (); 1532 fMethodNode.accept( 1533 new ASTVisitor() { 1534 public boolean visit(MethodInvocation invocation) { 1535 if (invocation.resolveMethodBinding() == null) 1536 return true; 1537 if(isImplicitThisMethodInvocation(invocation)) 1538 result.add(invocation); 1539 return true; 1540 } 1541 1542 private boolean isImplicitThisMethodInvocation(MethodInvocation invocation) { 1543 return ! isInvokedMethodStatic(invocation) 1544 && invocation.getExpression() == null; 1545 } 1546 1547 private boolean isInvokedMethodStatic(MethodInvocation invocation) { 1548 return JdtFlags.isStatic(invocation.resolveMethodBinding()); 1549 } 1550 } 1551 ); 1552 return (MethodInvocation[]) result.toArray(new MethodInvocation[result.size()]); 1553 } 1554 1555 private SimpleName[] getImplicitThisFieldAccesses() { 1556 final List result= new ArrayList (); 1557 fMethodNode.accept( 1558 new ASTVisitor() { 1559 public boolean visit(SimpleName name) { 1560 if(isImplicitThisFieldAccess(name)) 1561 result.add(name); 1562 return false; 1563 } 1564 } 1565 ); 1566 return (SimpleName[]) result.toArray(new SimpleName[result.size()]); 1567 } 1568 1569 public boolean hasSelfReferences(NewReceiver newReceiver) { 1570 return getExplicitThisReferences().length != 0 1571 || getImplicitThisMethodInvocations().length != 0 1572 || newReceiver.hasFieldsAccessesOtherThanToMe(getImplicitThisFieldAccesses()); 1573 } 1574 1575 private MethodDeclaration getDeclaration() { 1576 return fMethodNode; 1577 } 1578 1579 private IMethodBinding getBinding() { 1580 IMethodBinding binding= fMethodNode.resolveBinding(); 1581 Assert.isNotNull(binding); 1583 return binding; 1584 } 1585 1586 public ITypeBinding getReturnType() { 1587 return getBinding().getReturnType(); 1588 } 1589 1590 public boolean hasVoidReturnType() { 1591 Type returnType= fMethodNode.getReturnType(); 1592 if(!(returnType instanceof PrimitiveType)) 1593 return false; 1594 return PrimitiveType.VOID.equals(((PrimitiveType) returnType).getPrimitiveTypeCode()); 1595 } 1596 1597 public SimpleName createParameterReference(Parameter parameter) { 1598 Assert.isTrue(parameter.getMethod() == this); 1599 return fMethodNode.getAST().newSimpleName(parameter.getName()); 1600 } 1601 1602 private AST getAST() { 1603 return fMethodNode.getAST(); 1604 } 1605 1606 1607 private SingleVariableDeclaration getParameterDeclaration(Parameter parameter) { 1608 for(Iterator decls= fMethodNode.parameters().iterator(); decls.hasNext();) { 1609 SingleVariableDeclaration parameterDeclaration= (SingleVariableDeclaration) decls.next(); 1610 if(parameter.getBinding().equals(parameterDeclaration.resolveBinding())) 1611 return parameterDeclaration; 1612 } 1613 Assert.isTrue(false, "Parameter must be a parameter to this method."); return null; 1615 } 1616 1617 private TypeReferences getTypeReferences() { 1618 TypeReferences result= new TypeReferences(); 1619 result.addAllReferences(fMethodNode); 1620 return result; 1621 } 1622 1623 private Name[] findOutermostNonRightHandDotOperandNamesInBody() { 1624 final List result= new ArrayList (); 1625 fMethodNode.getBody().accept( 1626 new HierarchicalASTVisitor() { 1627 public boolean visit(Name name) { 1628 if(!isRightDotOperand(name)) 1629 result.add(name); 1630 return false; 1631 } 1632 } 1633 ); 1634 return (Name[]) result.toArray(new Name[result.size()]); 1635 } 1636 1637 public boolean equals(Object o) { 1638 if(o == null) 1639 return false; 1640 if(!getClass().equals(o.getClass())) 1641 return false; 1642 return getDeclaration().equals(((Method) o).getDeclaration()); 1643 } 1644 1645 1647 private static SimpleName getLeftmost(Name name) { 1648 if(name instanceof SimpleName) 1649 return (SimpleName) name; 1650 1651 return getLeftmost(((QualifiedName) name).getQualifier()); 1652 } 1653 1654 private static boolean isImplicitThisFieldAccess(SimpleName name) { 1655 return isInstanceFieldAccess(name) && !isRightDotOperand(name); 1656 } 1657 1658 1661 private static boolean isRightDotOperand(Name name) { 1662 ASTNode parent = name.getParent(); 1663 if(parent instanceof QualifiedName && ((QualifiedName)parent).getName().equals(name)) 1664 return true; 1665 1666 if(parent instanceof FieldAccess && ((FieldAccess)parent).getName().equals(name)) 1667 return true; 1668 1669 if(parent instanceof SuperFieldAccess) 1670 return true; 1671 1672 if(parent instanceof MethodInvocation) { 1673 MethodInvocation invocation= (MethodInvocation) parent; 1674 return invocation.getExpression() != null && invocation.getName().equals(name); 1675 } 1676 1677 return false; 1678 } 1679 1680 private static boolean isInstanceFieldAccess(SimpleName name) { 1681 IBinding binding= name.resolveBinding(); 1682 1684 if(!(binding instanceof IVariableBinding)) 1685 return false; 1686 1687 IVariableBinding variableBinding= (IVariableBinding) binding; 1688 if(!variableBinding.isField()) 1689 return false; 1690 1691 return !Modifier.isStatic(variableBinding.getModifiers()); 1692 } 1693 } 1694 1695 private static class Parameter implements IParameter { 1696 private final Method fMethod; 1697 private final IVariableBinding fBinding; 1698 1699 private Parameter(Method method, IVariableBinding binding) { 1700 Assert.isNotNull(method); 1701 Assert.isNotNull(binding); 1702 Assert.isTrue(!binding.isField()); 1703 1704 fMethod= method; 1705 fBinding= binding; 1706 } 1707 1708 public String getName() { 1709 return fBinding.getName(); 1710 } 1711 1712 public ITypeBinding getType() { 1713 return fBinding.getType(); 1714 } 1715 1716 public Method getMethod() { 1717 return fMethod; 1718 } 1719 1720 public boolean isFinal() { 1721 return Modifier.isFinal(fBinding.getModifiers()); 1722 } 1723 1724 public SimpleName createReference() { 1725 return fMethod.createParameterReference(this); 1726 } 1727 1728 public IVariableBinding getBinding() { 1729 return fBinding; 1730 } 1731 1732 public boolean equals(Object o) { 1733 if(o == null) 1734 return false; 1735 if(!getClass().equals((o.getClass()))) 1736 return false; 1737 Parameter otherParam= (Parameter) o; 1738 return getName().equals(otherParam.getName()) 1739 && getMethod().equals(otherParam.getMethod()); 1740 } 1741 } 1742 1743 private static class TextBufferPortion { 1744 private final TextBuffer fBuffer; 1745 private final RangeMarker fMarker; 1746 1747 TextBufferPortion(TextBuffer buffer, RangeMarker marker) { 1748 Assert.isNotNull(buffer); 1749 Assert.isNotNull(marker); 1750 fBuffer= buffer; 1751 fMarker= marker; 1752 } 1753 1754 public String getContent() { 1755 return fBuffer.getContent(fMarker.getOffset(), fMarker.getLength()); 1756 } 1757 1758 public String getUnindentedContentIgnoreFirstLine() { 1759 return Strings.changeIndent( 1760 fBuffer.getContent(fMarker.getOffset(), fMarker.getLength()), 1761 fBuffer.getLineIndent(fBuffer.getLineOfOffset(fMarker.getOffset()), CodeFormatterUtil.getTabWidth()), 1762 CodeFormatterUtil.getTabWidth(), 1763 "", fBuffer.getLineDelimiter() 1765 ); 1766 } 1767 } 1768 1769 private final Method fMethodToMove; 1770 1771 private NewReceiver fNewReceiver; 1772 1773 private String fNewMethodName; 1774 private String fOriginalReceiverParameterName; 1775 1776 private boolean fInlineDelegator; 1777 private boolean fRemoveDelegator; 1778 1779 public static InstanceMethodMover create(MethodDeclaration declaration, ICompilationUnit declarationCU, CodeGenerationSettings codeGenSettings) { 1780 Method method= Method.create(declaration, declarationCU, codeGenSettings); 1781 if (method == null) return null; 1782 return new InstanceMethodMover(method); 1783 } 1784 1785 private InstanceMethodMover(Method method) { 1786 Assert.isNotNull(method); 1787 fMethodToMove= method; 1788 1789 fInlineDelegator= true; fRemoveDelegator= true; fNewMethodName= fMethodToMove.getName(); fOriginalReceiverParameterName= guessOriginalReceiverParameterName(); } 1794 1795 private String guessOriginalReceiverParameterName() { 1796 ITypeBinding type= fMethodToMove.getDeclaringClass(); 1797 String typeName= getQualifiedName(type); 1798 if (typeName.length() == 0) 1799 return ""; String [] candidates= NamingConventions.suggestArgumentNames(fMethodToMove.getProject(), 1801 "", typeName, type.getDimensions(), getExcludedParameterNames()); if (candidates.length > 0) 1803 return candidates[0]; 1804 return ""; } 1806 1807 private static String getQualifiedName(ITypeBinding typeBinding) { 1808 if (typeBinding.isAnonymous()) 1809 return getQualifiedName(typeBinding.getSuperclass()); 1810 if (! typeBinding.isArray()) 1811 return typeBinding.getQualifiedName(); 1812 else 1813 return typeBinding.getElementType().getQualifiedName(); 1814 } 1815 1816 private String [] getExcludedParameterNames() { 1817 ArrayList names= new ArrayList (); 1818 MethodDeclaration methodDeclaration= fMethodToMove.getMethodDeclaration(); 1819 1820 List params= methodDeclaration.parameters(); 1821 for (int i= 0; i < params.size(); i++) { 1822 names.add(((SingleVariableDeclaration) params.get(i)).getName().getIdentifier()); 1823 } 1824 1825 Block body= methodDeclaration.getBody(); 1826 if (body != null) { IBinding[] variableBindings= new ScopeAnalyzer(((CompilationUnit) methodDeclaration.getRoot())). 1828 getDeclarationsAfter(body.getStartPosition(), ScopeAnalyzer.VARIABLES); 1829 for (int i= 0; i < variableBindings.length; i++) { 1830 names.add(variableBindings[i].getName()); 1831 } 1832 } 1833 return (String []) names.toArray(new String [names.size()]); 1834 } 1835 1836 public INewReceiver[] getPossibleNewReceivers() { 1837 return fMethodToMove.getPossibleNewReceivers(); 1838 } 1839 1840 1844 public void chooseNewReceiver(INewReceiver chosen) { 1845 Assert.isTrue(Arrays.asList(getPossibleNewReceivers()).contains(chosen)); 1846 fNewReceiver= (NewReceiver) chosen; 1847 } 1848 1849 public String getNewMethodName() { 1850 return fNewMethodName; 1851 } 1852 1853 public void setNewMethodName(String newMethodName) { 1854 Assert.isNotNull(newMethodName); 1855 fNewMethodName= newMethodName; 1856 } 1857 1858 public String getOriginalReceiverParameterName() { 1859 return fOriginalReceiverParameterName; 1860 } 1861 1862 public void setOriginalReceiverParameterName(String originalReceiverParameterName) { 1863 Assert.isNotNull(originalReceiverParameterName); 1864 fOriginalReceiverParameterName= originalReceiverParameterName; 1865 } 1866 1867 public void setInlineDelegator(boolean inlineDelegator) { 1868 fInlineDelegator= inlineDelegator; 1869 checkInvariant(); 1870 } 1871 1872 public void setRemoveDelegator(boolean removeDelegator) { 1873 fRemoveDelegator= removeDelegator; 1874 checkInvariant(); 1875 } 1876 1877 public boolean getInlineDelegator() { 1878 return fInlineDelegator; 1879 } 1880 1881 public boolean getRemoveDelegator() { 1882 return fRemoveDelegator; 1883 } 1884 1885 private void checkInvariant() { 1886 if(fRemoveDelegator) 1887 Assert.isTrue(fInlineDelegator); 1888 } 1889 1890 private static IType getModelClass(ITypeBinding clazz, IJavaProject dependentProject) throws JavaModelException { 1891 Assert.isTrue(clazz.isClass()); 1892 IType modelClass= Bindings.findType(clazz, dependentProject); 1893 if(modelClass == null || !modelClass.exists()) 1894 return null; 1895 1896 Assert.isTrue(modelClass.isClass()); 1897 return modelClass; 1898 } 1899 1900 public RefactoringStatus checkInitialState() { 1901 return fMethodToMove.checkCanBeMoved(); 1902 } 1903 1904 public final RefactoringStatus checkInput(IProgressMonitor pm, Object validationContext) throws JavaModelException { 1905 pm.beginTask("", 1); try{ 1907 Assert.isNotNull(fNewReceiver, "New receiver must be chosen before checkInput(..) is called."); return fNewReceiver.checkMoveOfMethodToMe(fMethodToMove, fNewMethodName, 1909 fOriginalReceiverParameterName, fInlineDelegator, 1910 fRemoveDelegator, validationContext); 1911 }finally{ 1912 pm.done(); 1913 } 1914 } 1915 1916 public Change createChange(IProgressMonitor pm) throws CoreException { 1917 try{ 1918 pm.beginTask("", 1); return fNewReceiver.moveMethodToMe(fMethodToMove, fNewMethodName, fOriginalReceiverParameterName, fInlineDelegator, fRemoveDelegator); 1920 }finally{ 1921 pm.done(); 1922 } 1923 } 1924} 1925 | Popular Tags |