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.HashMap ; 16 import java.util.HashSet ; 17 import java.util.Iterator ; 18 import java.util.LinkedHashMap ; 19 import java.util.List ; 20 import java.util.Map ; 21 import java.util.Set ; 22 import java.util.StringTokenizer ; 23 24 import org.eclipse.text.edits.TextEditGroup; 25 26 import org.eclipse.core.runtime.Assert; 27 import org.eclipse.core.runtime.CoreException; 28 import org.eclipse.core.runtime.IProgressMonitor; 29 import org.eclipse.core.runtime.NullProgressMonitor; 30 import org.eclipse.core.runtime.OperationCanceledException; 31 import org.eclipse.core.runtime.SubProgressMonitor; 32 33 import org.eclipse.core.resources.IFile; 34 35 import org.eclipse.ltk.core.refactoring.Change; 36 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; 37 import org.eclipse.ltk.core.refactoring.RefactoringStatus; 38 import org.eclipse.ltk.core.refactoring.RefactoringStatusContext; 39 import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry; 40 import org.eclipse.ltk.core.refactoring.TextChange; 41 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments; 42 43 import org.eclipse.jdt.core.Flags; 44 import org.eclipse.jdt.core.ICompilationUnit; 45 import org.eclipse.jdt.core.IJavaElement; 46 import org.eclipse.jdt.core.IJavaProject; 47 import org.eclipse.jdt.core.IMethod; 48 import org.eclipse.jdt.core.IType; 49 import org.eclipse.jdt.core.ITypeHierarchy; 50 import org.eclipse.jdt.core.JavaModelException; 51 import org.eclipse.jdt.core.Signature; 52 import org.eclipse.jdt.core.compiler.IProblem; 53 import org.eclipse.jdt.core.dom.AST; 54 import org.eclipse.jdt.core.dom.ASTNode; 55 import org.eclipse.jdt.core.dom.ASTParser; 56 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; 57 import org.eclipse.jdt.core.dom.Block; 58 import org.eclipse.jdt.core.dom.BodyDeclaration; 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.EnumConstantDeclaration; 63 import org.eclipse.jdt.core.dom.EnumDeclaration; 64 import org.eclipse.jdt.core.dom.Expression; 65 import org.eclipse.jdt.core.dom.IMethodBinding; 66 import org.eclipse.jdt.core.dom.ITypeBinding; 67 import org.eclipse.jdt.core.dom.ImportDeclaration; 68 import org.eclipse.jdt.core.dom.Javadoc; 69 import org.eclipse.jdt.core.dom.MemberRef; 70 import org.eclipse.jdt.core.dom.MethodDeclaration; 71 import org.eclipse.jdt.core.dom.MethodInvocation; 72 import org.eclipse.jdt.core.dom.MethodRef; 73 import org.eclipse.jdt.core.dom.MethodRefParameter; 74 import org.eclipse.jdt.core.dom.Modifier; 75 import org.eclipse.jdt.core.dom.Name; 76 import org.eclipse.jdt.core.dom.PrimitiveType; 77 import org.eclipse.jdt.core.dom.QualifiedName; 78 import org.eclipse.jdt.core.dom.SimpleName; 79 import org.eclipse.jdt.core.dom.SingleVariableDeclaration; 80 import org.eclipse.jdt.core.dom.SuperConstructorInvocation; 81 import org.eclipse.jdt.core.dom.SuperMethodInvocation; 82 import org.eclipse.jdt.core.dom.TagElement; 83 import org.eclipse.jdt.core.dom.TextElement; 84 import org.eclipse.jdt.core.dom.Type; 85 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; 86 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; 87 import org.eclipse.jdt.core.dom.rewrite.ListRewrite; 88 import org.eclipse.jdt.core.refactoring.IJavaRefactorings; 89 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor; 90 import org.eclipse.jdt.core.search.IJavaSearchConstants; 91 import org.eclipse.jdt.core.search.IJavaSearchScope; 92 import org.eclipse.jdt.core.search.SearchPattern; 93 94 import org.eclipse.jdt.internal.corext.Corext; 95 import org.eclipse.jdt.internal.corext.SourceRange; 96 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility; 97 import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory; 98 import org.eclipse.jdt.internal.corext.dom.ASTNodes; 99 import org.eclipse.jdt.internal.corext.dom.Bindings; 100 import org.eclipse.jdt.internal.corext.dom.ModifierRewrite; 101 import org.eclipse.jdt.internal.corext.dom.NodeFinder; 102 import org.eclipse.jdt.internal.corext.dom.Selection; 103 import org.eclipse.jdt.internal.corext.dom.SelectionAnalyzer; 104 import org.eclipse.jdt.internal.corext.refactoring.Checks; 105 import org.eclipse.jdt.internal.corext.refactoring.ExceptionInfo; 106 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor; 107 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment; 108 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments; 109 import org.eclipse.jdt.internal.corext.refactoring.ParameterInfo; 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.RefactoringSearchEngine; 113 import org.eclipse.jdt.internal.corext.refactoring.ReturnTypeInfo; 114 import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup; 115 import org.eclipse.jdt.internal.corext.refactoring.StubTypeContext; 116 import org.eclipse.jdt.internal.corext.refactoring.TypeContextChecker; 117 import org.eclipse.jdt.internal.corext.refactoring.TypeContextChecker.IProblemVerifier; 118 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext; 119 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStringStatusContext; 120 import org.eclipse.jdt.internal.corext.refactoring.base.RefactoringStatusCodes; 121 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange; 122 import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring; 123 import org.eclipse.jdt.internal.corext.refactoring.delegates.DelegateMethodCreator; 124 import org.eclipse.jdt.internal.corext.refactoring.rename.MethodChecks; 125 import org.eclipse.jdt.internal.corext.refactoring.rename.RefactoringAnalyzeUtil; 126 import org.eclipse.jdt.internal.corext.refactoring.rename.RippleMethodFinder2; 127 import org.eclipse.jdt.internal.corext.refactoring.rename.TempOccurrenceAnalyzer; 128 import org.eclipse.jdt.internal.corext.refactoring.tagging.IDelegateUpdating; 129 import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil; 130 import org.eclipse.jdt.internal.corext.refactoring.util.JavadocUtil; 131 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser; 132 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil; 133 import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager; 134 import org.eclipse.jdt.internal.corext.refactoring.util.TightSourceRangeComputer; 135 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 136 import org.eclipse.jdt.internal.corext.util.JdtFlags; 137 import org.eclipse.jdt.internal.corext.util.Messages; 138 139 import org.eclipse.jdt.ui.JavaElementLabels; 140 141 import org.eclipse.jdt.internal.ui.JavaPlugin; 142 143 public class ChangeSignatureRefactoring extends ScriptableRefactoring implements IDelegateUpdating { 144 145 private static final String ATTRIBUTE_RETURN= "return"; private static final String ATTRIBUTE_VISIBILITY= "visibility"; private static final String ATTRIBUTE_PARAMETER= "parameter"; private static final String ATTRIBUTE_DEFAULT= "default"; private static final String ATTRIBUTE_KIND= "kind"; private static final String ATTRIBUTE_DELEGATE= "delegate"; private static final String ATTRIBUTE_DEPRECATE= "deprecate"; 153 private List fParameterInfos; 154 155 private CompilationUnitRewrite fBaseCuRewrite; 156 private List fExceptionInfos; 157 protected TextChangeManager fChangeManager; 158 protected List fOtherChanges; 159 private IMethod fMethod; 160 private IMethod fTopMethod; 161 private IMethod[] fRippleMethods; 162 private SearchResultGroup[] fOccurrences; 163 private ReturnTypeInfo fReturnTypeInfo; 164 private String fMethodName; 165 private int fVisibility; 166 private static final String CONST_CLASS_DECL = "class A{"; private static final String CONST_ASSIGN = " i="; private static final String CONST_CLOSE = ";}"; 170 private StubTypeContext fContextCuStartEnd; 171 private int fOldVarargIndex; 173 private BodyUpdater fBodyUpdater; 174 private IDefaultValueAdvisor fDefaultValueAdvisor; 175 176 private ITypeHierarchy fCachedTypeHierarchy= null; 177 private boolean fDelegateUpdating; 178 private boolean fDelegateDeprecation; 179 180 185 public ChangeSignatureRefactoring(IMethod method) throws JavaModelException { 186 fMethod= method; 187 fOldVarargIndex= -1; 188 fDelegateUpdating= false; 189 fDelegateDeprecation= true; 190 if (fMethod != null) { 191 fParameterInfos= createParameterInfoList(method); 192 fReturnTypeInfo= new ReturnTypeInfo(Signature.toString(Signature.getReturnType(fMethod.getSignature()))); 194 fMethodName= fMethod.getElementName(); 195 fVisibility= JdtFlags.getVisibilityCode(fMethod); 196 } 197 } 198 199 private static List createParameterInfoList(IMethod method) { 200 try { 201 String [] typeNames= method.getParameterTypes(); 202 String [] oldNames= method.getParameterNames(); 203 List result= new ArrayList (typeNames.length); 204 for (int i= 0; i < oldNames.length; i++){ 205 ParameterInfo parameterInfo; 206 if (i == oldNames.length - 1 && Flags.isVarargs(method.getFlags())) { 207 String varargSignature= typeNames[i]; 208 int arrayCount= Signature.getArrayCount(varargSignature); 209 String baseSignature= Signature.getElementType(varargSignature); 210 if (arrayCount > 1) 211 baseSignature= Signature.createArraySignature(baseSignature, arrayCount - 1); 212 parameterInfo= new ParameterInfo(Signature.toString(baseSignature) + ParameterInfo.ELLIPSIS, oldNames[i], i); 213 } else { 214 parameterInfo= new ParameterInfo(Signature.toString(typeNames[i]), oldNames[i], i); 215 } 216 result.add(parameterInfo); 217 } 218 return result; 219 } catch(JavaModelException e) { 220 JavaPlugin.log(e); 221 return new ArrayList (0); 222 } 223 } 224 225 228 public String getName() { 229 return RefactoringCoreMessages.ChangeSignatureRefactoring_modify_Parameters; 230 } 231 232 public IMethod getMethod() { 233 return fMethod; 234 } 235 236 public String getMethodName() { 237 return fMethodName; 238 } 239 240 public String getReturnTypeString() { 241 return fReturnTypeInfo.getNewTypeName(); 242 } 243 244 public void setNewMethodName(String newMethodName){ 245 Assert.isNotNull(newMethodName); 246 fMethodName= newMethodName; 247 } 248 249 public void setNewReturnTypeName(String newReturnTypeName){ 250 Assert.isNotNull(newReturnTypeName); 251 fReturnTypeInfo.setNewTypeName(newReturnTypeName); 252 } 253 254 public boolean canChangeNameAndReturnType(){ 255 try { 256 return ! fMethod.isConstructor(); 257 } catch (JavaModelException e) { 258 JavaPlugin.log(e); 259 return false; 260 } 261 } 262 263 267 public int getVisibility(){ 268 return fVisibility; 269 } 270 271 275 public void setVisibility(int visibility){ 276 Assert.isTrue( visibility == Modifier.PUBLIC || 277 visibility == Modifier.PROTECTED || 278 visibility == Modifier.NONE || 279 visibility == Modifier.PRIVATE); 280 fVisibility= visibility; 281 } 282 283 286 public int[] getAvailableVisibilities() throws JavaModelException{ 287 if (fTopMethod.getDeclaringType().isInterface()) 288 return new int[]{Modifier.PUBLIC}; 289 else if (fTopMethod.getDeclaringType().isEnum() && fTopMethod.isConstructor()) 290 return new int[]{ Modifier.NONE, 291 Modifier.PRIVATE}; 292 else 293 return new int[]{ Modifier.PUBLIC, 294 Modifier.PROTECTED, 295 Modifier.NONE, 296 Modifier.PRIVATE}; 297 } 298 299 303 public List getParameterInfos(){ 304 return fParameterInfos; 305 } 306 307 310 public List getExceptionInfos(){ 311 return fExceptionInfos; 312 } 313 314 public void setBodyUpdater(BodyUpdater bodyUpdater) { 315 fBodyUpdater= bodyUpdater; 316 } 317 318 public CompilationUnitRewrite getBaseCuRewrite() { 319 return fBaseCuRewrite; 320 } 321 322 324 public boolean canEnableDelegateUpdating() { 325 return true; 326 } 327 328 public boolean getDelegateUpdating() { 329 return fDelegateUpdating; 330 } 331 332 public void setDelegateUpdating(boolean updating) { 333 fDelegateUpdating= updating; 334 } 335 336 public void setDeprecateDelegates(boolean deprecate) { 337 fDelegateDeprecation= deprecate; 338 } 339 340 public boolean getDeprecateDelegates() { 341 return fDelegateDeprecation; 342 } 343 344 346 public RefactoringStatus checkSignature() { 347 return checkSignature(false, doGetProblemVerifier()); 348 } 349 350 private RefactoringStatus checkSignature(boolean resolveBindings, IProblemVerifier problemVerifier) { 351 RefactoringStatus result= new RefactoringStatus(); 352 checkMethodName(result); 353 if (result.hasFatalError()) 354 return result; 355 356 checkParameterNamesAndValues(result); 357 if (result.hasFatalError()) 358 return result; 359 360 checkForDuplicateParameterNames(result); 361 if (result.hasFatalError()) 362 return result; 363 364 try { 365 RefactoringStatus[] typeStati; 366 if (resolveBindings) 367 typeStati= TypeContextChecker.checkAndResolveMethodTypes(fMethod, getStubTypeContext(), getNotDeletedInfos(), fReturnTypeInfo, problemVerifier); 368 else 369 typeStati= TypeContextChecker.checkMethodTypesSyntax(fMethod, getNotDeletedInfos(), fReturnTypeInfo); 370 for (int i= 0; i < typeStati.length; i++) 371 result.merge(typeStati[i]); 372 373 result.merge(checkVarargs()); 374 } catch (CoreException e) { 375 throw new RuntimeException (e); 377 } 378 379 return result; 381 } 382 383 public boolean isSignatureSameAsInitial() throws JavaModelException { 384 if (! isVisibilitySameAsInitial()) 385 return false; 386 if (! isMethodNameSameAsInitial()) 387 return false; 388 if (! isReturnTypeSameAsInitial()) 389 return false; 390 if (! areExceptionsSameAsInitial()) 391 return false; 392 393 if (fMethod.getNumberOfParameters() == 0 && fParameterInfos.isEmpty()) 394 return true; 395 396 if (areNamesSameAsInitial() && isOrderSameAsInitial() && areParameterTypesSameAsInitial()) 397 return true; 398 399 return false; 400 } 401 402 407 public boolean isSignatureClashWithInitial() throws JavaModelException { 408 409 if (!isMethodNameSameAsInitial()) 410 return false; 412 if (fMethod.getNumberOfParameters() == 0 && fParameterInfos.isEmpty()) 413 return true; 415 418 int no= getNotDeletedInfos().size(); 419 420 if (fMethod.getNumberOfParameters() != no) 421 return false; 422 423 426 if (isOrderSameAsInitial()) 427 return areParameterTypesSameAsInitial(); 428 else 429 return false; } 431 432 private boolean areParameterTypesSameAsInitial() { 433 for (Iterator iter= fParameterInfos.iterator(); iter.hasNext();) { 434 ParameterInfo info= (ParameterInfo) iter.next(); 435 if (! info.isAdded() && ! info.isDeleted() && info.isTypeNameChanged()) 436 return false; 437 } 438 return true; 439 } 440 441 private boolean isReturnTypeSameAsInitial() throws JavaModelException { 442 return ! fReturnTypeInfo.isTypeNameChanged(); 443 } 444 445 private boolean isMethodNameSameAsInitial() { 446 return fMethodName.equals(fMethod.getElementName()); 447 } 448 449 private boolean areExceptionsSameAsInitial() { 450 for (Iterator iter= fExceptionInfos.iterator(); iter.hasNext();) { 451 ExceptionInfo info= (ExceptionInfo) iter.next(); 452 if (! info.isOld()) 453 return false; 454 } 455 return true; 456 } 457 458 private void checkParameterNamesAndValues(RefactoringStatus result) { 459 int i= 1; 460 for (Iterator iter= fParameterInfos.iterator(); iter.hasNext(); i++) { 461 ParameterInfo info= (ParameterInfo) iter.next(); 462 if (info.isDeleted()) 463 continue; 464 checkParameterName(result, info, i); 465 if (result.hasFatalError()) 466 return; 467 if (info.isAdded()) { 468 checkParameterDefaultValue(result, info); 469 if (result.hasFatalError()) 470 return; 471 } 472 } 473 } 474 475 private void checkParameterName(RefactoringStatus result, ParameterInfo info, int position) { 476 if (info.getNewName().trim().length() == 0) { 477 result.addFatalError(Messages.format( 478 RefactoringCoreMessages.ChangeSignatureRefactoring_param_name_not_empty, Integer.toString(position))); 479 } else { 480 result.merge(Checks.checkTempName(info.getNewName())); 481 } 482 } 483 484 private void checkMethodName(RefactoringStatus result) { 485 if (isMethodNameSameAsInitial() || ! canChangeNameAndReturnType()) 486 return; 487 if ("".equals(fMethodName.trim())) { String msg= RefactoringCoreMessages.ChangeSignatureRefactoring_method_name_not_empty; 489 result.addFatalError(msg); 490 return; 491 } 492 if (fMethodName.equals(fMethod.getDeclaringType().getElementName())) { 493 String msg= RefactoringCoreMessages.ChangeSignatureRefactoring_constructor_name; 494 result.addWarning(msg); 495 } 496 result.merge(Checks.checkMethodName(fMethodName)); 497 } 498 499 private void checkParameterDefaultValue(RefactoringStatus result, ParameterInfo info) { 500 if (fDefaultValueAdvisor != null) 501 return; 502 if (info.isNewVarargs()) { 503 if (! isValidVarargsExpression(info.getDefaultValue())){ 504 String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_invalid_expression, new String []{info.getDefaultValue()}); 505 result.addFatalError(msg); 506 } 507 return; 508 } 509 510 if (info.getDefaultValue().trim().equals("")){ String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_default_value, new String []{info.getNewName()}); 512 result.addFatalError(msg); 513 return; 514 } 515 if (! isValidExpression(info.getDefaultValue())){ 516 String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_invalid_expression, new String []{info.getDefaultValue()}); 517 result.addFatalError(msg); 518 } 519 } 520 521 private RefactoringStatus checkVarargs() throws JavaModelException { 522 RefactoringStatus result= checkOriginalVarargs(); 523 if (result != null) 524 return result; 525 526 if (fRippleMethods != null) { 527 for (int iRipple= 0; iRipple < fRippleMethods.length; iRipple++) { 528 IMethod rippleMethod= fRippleMethods[iRipple]; 529 if (! JdtFlags.isVarargs(rippleMethod)) 530 continue; 531 532 fOldVarargIndex= rippleMethod.getNumberOfParameters() - 1; 534 List notDeletedInfos= getNotDeletedInfos(); 535 for (int i= 0; i < notDeletedInfos.size(); i++) { 536 ParameterInfo info= (ParameterInfo) notDeletedInfos.get(i); 537 if (fOldVarargIndex != -1 && info.getOldIndex() == fOldVarargIndex && ! info.isNewVarargs()) { 538 String rippleMethodType= JavaModelUtil.getFullyQualifiedName(rippleMethod.getDeclaringType()); 539 String message= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_ripple_cannot_convert_vararg, new Object [] {info.getNewName(), rippleMethodType}); 540 return RefactoringStatus.createFatalErrorStatus(message, JavaStatusContext.create(rippleMethod)); 541 } 542 } 543 } 544 } 545 546 return null; 547 } 548 549 private RefactoringStatus checkOriginalVarargs() throws JavaModelException { 550 if (JdtFlags.isVarargs(fMethod)) 551 fOldVarargIndex= fMethod.getNumberOfParameters() - 1; 552 List notDeletedInfos= getNotDeletedInfos(); 553 for (int i= 0; i < notDeletedInfos.size(); i++) { 554 ParameterInfo info= (ParameterInfo) notDeletedInfos.get(i); 555 if (info.isOldVarargs() && ! info.isNewVarargs()) 556 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_cannot_convert_vararg, info.getNewName())); 557 if (i != notDeletedInfos.size() - 1) { 558 if (info.isNewVarargs()) 560 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_vararg_must_be_last, info.getNewName())); 561 } 562 } 563 return null; 564 } 565 566 private RefactoringStatus checkTypeVariables() throws JavaModelException { 567 if (fRippleMethods.length == 1) 568 return null; 569 570 RefactoringStatus result= new RefactoringStatus(); 571 if (fReturnTypeInfo.isTypeNameChanged() && fReturnTypeInfo.getNewTypeBinding() != null) { 572 HashSet typeVariablesCollector= new HashSet (); 573 collectTypeVariables(fReturnTypeInfo.getNewTypeBinding(), typeVariablesCollector); 574 if (typeVariablesCollector.size() != 0) { 575 ITypeBinding first= (ITypeBinding) typeVariablesCollector.iterator().next(); 576 String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_return_type_contains_type_variable, new String [] {fReturnTypeInfo.getNewTypeName(), first.getName()}); 577 result.addError(msg); 578 } 579 } 580 581 for (Iterator iter= getNotDeletedInfos().iterator(); iter.hasNext();) { 582 ParameterInfo info= (ParameterInfo) iter.next(); 583 if (info.isTypeNameChanged() && info.getNewTypeBinding() != null) { 584 HashSet typeVariablesCollector= new HashSet (); 585 collectTypeVariables(info.getNewTypeBinding(), typeVariablesCollector); 586 if (typeVariablesCollector.size() != 0) { 587 ITypeBinding first= (ITypeBinding) typeVariablesCollector.iterator().next(); 588 String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_parameter_type_contains_type_variable, new String [] {info.getNewTypeName(), info.getNewName(), first.getName()}); 589 result.addError(msg); 590 } 591 } 592 } 593 return result; 594 } 595 596 private void collectTypeVariables(ITypeBinding typeBinding, Set typeVariablesCollector) { 597 if (typeBinding.isTypeVariable()) { 598 typeVariablesCollector.add(typeBinding); 599 ITypeBinding[] typeBounds= typeBinding.getTypeBounds(); 600 for (int i= 0; i < typeBounds.length; i++) 601 collectTypeVariables(typeBounds[i], typeVariablesCollector); 602 603 } else if (typeBinding.isArray()) { 604 collectTypeVariables(typeBinding.getElementType(), typeVariablesCollector); 605 606 } else if (typeBinding.isParameterizedType()) { 607 ITypeBinding[] typeArguments= typeBinding.getTypeArguments(); 608 for (int i= 0; i < typeArguments.length; i++) 609 collectTypeVariables(typeArguments[i], typeVariablesCollector); 610 611 } else if (typeBinding.isWildcardType()) { 612 ITypeBinding bound= typeBinding.getBound(); 613 if (bound != null) { 614 collectTypeVariables(bound, typeVariablesCollector); 615 } 616 } 617 } 618 619 public static boolean isValidExpression(String string){ 620 String trimmed= string.trim(); 621 if ("".equals(trimmed)) return false; 623 StringBuffer cuBuff= new StringBuffer (); 624 cuBuff.append(CONST_CLASS_DECL) 625 .append("Object") .append(CONST_ASSIGN); 627 int offset= cuBuff.length(); 628 cuBuff.append(trimmed) 629 .append(CONST_CLOSE); 630 ASTParser p= ASTParser.newParser(AST.JLS3); 631 p.setSource(cuBuff.toString().toCharArray()); 632 CompilationUnit cu= (CompilationUnit) p.createAST(null); 633 Selection selection= Selection.createFromStartLength(offset, trimmed.length()); 634 SelectionAnalyzer analyzer= new SelectionAnalyzer(selection, false); 635 cu.accept(analyzer); 636 ASTNode selected= analyzer.getFirstSelectedNode(); 637 return (selected instanceof Expression) && 638 trimmed.equals(cuBuff.substring(cu.getExtendedStartPosition(selected), cu.getExtendedStartPosition(selected) + cu.getExtendedLength(selected))); 639 } 640 641 public static boolean isValidVarargsExpression(String string) { 642 String trimmed= string.trim(); 643 if ("".equals(trimmed)) return true; 645 StringBuffer cuBuff= new StringBuffer (); 646 cuBuff.append("class A{ {m("); int offset= cuBuff.length(); 648 cuBuff.append(trimmed) 649 .append(");}}"); ASTParser p= ASTParser.newParser(AST.JLS3); 651 p.setSource(cuBuff.toString().toCharArray()); 652 CompilationUnit cu= (CompilationUnit) p.createAST(null); 653 Selection selection= Selection.createFromStartLength(offset, trimmed.length()); 654 SelectionAnalyzer analyzer= new SelectionAnalyzer(selection, false); 655 cu.accept(analyzer); 656 ASTNode[] selectedNodes= analyzer.getSelectedNodes(); 657 if (selectedNodes.length == 0) 658 return false; 659 for (int i= 0; i < selectedNodes.length; i++) { 660 if (! (selectedNodes[i] instanceof Expression)) 661 return false; 662 } 663 return true; 664 } 665 666 public StubTypeContext getStubTypeContext() { 667 try { 668 if (fContextCuStartEnd == null) 669 fContextCuStartEnd= TypeContextChecker.createStubTypeContext(getCu(), fBaseCuRewrite.getRoot(), fMethod.getSourceRange().getOffset()); 670 } catch (CoreException e) { 671 throw new RuntimeException (e); 673 } 674 return fContextCuStartEnd; 675 } 676 677 private ITypeHierarchy getCachedTypeHierarchy(IProgressMonitor monitor) throws JavaModelException { 678 if (fCachedTypeHierarchy == null) 679 fCachedTypeHierarchy= fMethod.getDeclaringType().newTypeHierarchy(new SubProgressMonitor(monitor, 1)); 680 return fCachedTypeHierarchy; 681 } 682 683 686 public RefactoringStatus checkInitialConditions(IProgressMonitor monitor) throws CoreException { 687 try { 688 monitor.beginTask("", 5); RefactoringStatus result= Checks.checkIfCuBroken(fMethod); 690 if (result.hasFatalError()) 691 return result; 692 if (fMethod == null || !fMethod.exists()) { 693 String message= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_method_deleted, getCu().getElementName()); 694 return RefactoringStatus.createFatalErrorStatus(message); 695 } 696 if (fMethod.getDeclaringType().isInterface()) { 697 fTopMethod= MethodChecks.overridesAnotherMethod(fMethod, fMethod.getDeclaringType().newSupertypeHierarchy(new SubProgressMonitor(monitor, 1))); 698 monitor.worked(1); 699 } else if (MethodChecks.isVirtual(fMethod)) { 700 ITypeHierarchy hierarchy= getCachedTypeHierarchy(new SubProgressMonitor(monitor, 1)); 701 fTopMethod= MethodChecks.isDeclaredInInterface(fMethod, hierarchy, new SubProgressMonitor(monitor, 1)); 702 if (fTopMethod == null) 703 fTopMethod= MethodChecks.overridesAnotherMethod(fMethod, hierarchy); 704 } 705 if (fTopMethod == null) 706 fTopMethod= fMethod; 707 if (! fTopMethod.equals(fMethod)) { 708 if (fTopMethod.getDeclaringType().isInterface()) { 709 RefactoringStatusContext context= JavaStatusContext.create(fTopMethod); 710 String message= Messages.format(RefactoringCoreMessages.MethodChecks_implements, 711 new String []{JavaElementUtil.createMethodSignature(fTopMethod), JavaModelUtil.getFullyQualifiedName(fTopMethod.getDeclaringType())}); 712 return RefactoringStatus.createStatus(RefactoringStatus.FATAL, message, context, Corext.getPluginId(), RefactoringStatusCodes.METHOD_DECLARED_IN_INTERFACE, fTopMethod); 713 } else { 714 RefactoringStatusContext context= JavaStatusContext.create(fTopMethod); 715 String message= Messages.format(RefactoringCoreMessages.MethodChecks_overrides, 716 new String []{JavaElementUtil.createMethodSignature(fTopMethod), JavaModelUtil.getFullyQualifiedName(fTopMethod.getDeclaringType())}); 717 return RefactoringStatus.createStatus(RefactoringStatus.FATAL, message, context, Corext.getPluginId(), RefactoringStatusCodes.OVERRIDES_ANOTHER_METHOD, fTopMethod); 718 } 719 } 720 721 if (monitor.isCanceled()) 722 throw new OperationCanceledException(); 723 724 if (fBaseCuRewrite == null || !fBaseCuRewrite.getCu().equals(getCu())) { 725 fBaseCuRewrite= new CompilationUnitRewrite(getCu()); 726 fBaseCuRewrite.getASTRewrite().setTargetSourceRangeComputer(new TightSourceRangeComputer()); 727 } 728 monitor.worked(1); 729 result.merge(createExceptionInfoList()); 730 monitor.worked(1); 731 return result; 732 } finally { 733 monitor.done(); 734 } 735 } 736 737 private RefactoringStatus createExceptionInfoList() { 738 if (fExceptionInfos == null || fExceptionInfos.isEmpty()) { 739 fExceptionInfos= new ArrayList (0); 740 try { 741 ASTNode nameNode= NodeFinder.perform(fBaseCuRewrite.getRoot(), fMethod.getNameRange()); 742 if (nameNode == null || !(nameNode instanceof Name) || !(nameNode.getParent() instanceof MethodDeclaration)) 743 return null; 744 MethodDeclaration methodDeclaration= (MethodDeclaration) nameNode.getParent(); 745 List exceptions= methodDeclaration.thrownExceptions(); 746 List result= new ArrayList (exceptions.size()); 747 for (int i= 0; i < exceptions.size(); i++) { 748 Name name= (Name) exceptions.get(i); 749 ITypeBinding typeBinding= name.resolveTypeBinding(); 750 if (typeBinding == null) 751 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeSignatureRefactoring_no_exception_binding); 752 IType type= (IType) typeBinding.getJavaElement(); 753 result.add(ExceptionInfo.createInfoForOldException(type, typeBinding)); 754 } 755 fExceptionInfos= result; 756 } catch (JavaModelException e) { 757 JavaPlugin.log(e); 758 } 759 } 760 return null; 761 } 762 763 766 public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException { 767 try { 768 pm.beginTask(RefactoringCoreMessages.ChangeSignatureRefactoring_checking_preconditions, 8); 769 RefactoringStatus result= new RefactoringStatus(); 770 clearManagers(); 771 fBaseCuRewrite.clearASTAndImportRewrites(); 772 fBaseCuRewrite.getASTRewrite().setTargetSourceRangeComputer(new TightSourceRangeComputer()); 773 774 if (isSignatureSameAsInitial()) 775 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeSignatureRefactoring_unchanged); 776 result.merge(checkSignature(true, doGetProblemVerifier())); 777 if (result.hasFatalError()) 778 return result; 779 780 if (fDelegateUpdating && isSignatureClashWithInitial()) 781 result.merge(RefactoringStatus.createErrorStatus(RefactoringCoreMessages.ChangeSignatureRefactoring_old_and_new_signatures_not_sufficiently_different )); 782 783 fRippleMethods= RippleMethodFinder2.getRelatedMethods(fMethod, new SubProgressMonitor(pm, 1), null); 784 result.merge(checkVarargs()); 785 if (result.hasFatalError()) 786 return result; 787 788 fOccurrences= findOccurrences(new SubProgressMonitor(pm, 1), result); 789 790 result.merge(checkVisibilityChanges()); 791 result.merge(checkTypeVariables()); 792 793 797 if (! isOrderSameAsInitial()) 798 result.merge(checkReorderings(new SubProgressMonitor(pm, 1))); 799 else 800 pm.worked(1); 801 802 806 if (! areNamesSameAsInitial()) 807 result.merge(checkRenamings(new SubProgressMonitor(pm, 1))); 808 else 809 pm.worked(1); 810 if (result.hasFatalError()) 811 return result; 812 813 815 createChangeManager(new SubProgressMonitor(pm, 1), result); 816 fCachedTypeHierarchy= null; 817 818 if (mustAnalyzeAstOfDeclaringCu()) 819 result.merge(checkCompilationofDeclaringCu()); if (result.hasFatalError()) 821 return result; 822 823 result.merge(validateModifiesFiles()); 824 return result; 825 } finally { 826 pm.done(); 827 } 828 } 829 830 protected IProblemVerifier doGetProblemVerifier() { 831 return null; 832 } 833 834 private void clearManagers() { 835 fChangeManager= null; 836 fOtherChanges= new ArrayList (); 837 } 838 839 private RefactoringStatus checkVisibilityChanges() throws JavaModelException { 840 if (isVisibilitySameAsInitial()) 841 return null; 842 if (fRippleMethods.length == 1) 843 return null; 844 Assert.isTrue(JdtFlags.getVisibilityCode(fMethod) != Modifier.PRIVATE); 845 if (fVisibility == Modifier.PRIVATE) 846 return RefactoringStatus.createWarningStatus(RefactoringCoreMessages.ChangeSignatureRefactoring_non_virtual); 847 return null; 848 } 849 850 public String getOldMethodSignature() throws JavaModelException{ 851 StringBuffer buff= new StringBuffer (); 852 853 int flags= getMethod().getFlags(); 854 buff.append(getVisibilityString(flags)); 855 if (Flags.isStatic(flags)) 856 buff.append("static "); if (! getMethod().isConstructor()) 858 buff.append(fReturnTypeInfo.getOldTypeName()) 859 .append(' '); 860 861 buff.append(JavaElementLabels.getElementLabel(fMethod.getParent(), JavaElementLabels.ALL_FULLY_QUALIFIED)); 862 buff.append('.'); 863 buff.append(fMethod.getElementName()) 864 .append(Signature.C_PARAM_START) 865 .append(getOldMethodParameters()) 866 .append(Signature.C_PARAM_END); 867 868 buff.append(getOldMethodThrows()); 869 870 return buff.toString(); 871 } 872 873 public String getNewMethodSignature() throws JavaModelException{ 874 StringBuffer buff= new StringBuffer (); 875 876 buff.append(getVisibilityString(fVisibility)); 877 if (Flags.isStatic(getMethod().getFlags())) 878 buff.append("static "); if (! getMethod().isConstructor()) 880 buff.append(getReturnTypeString()) 881 .append(' '); 882 883 buff.append(getMethodName()) 884 .append(Signature.C_PARAM_START) 885 .append(getMethodParameters()) 886 .append(Signature.C_PARAM_END); 887 888 buff.append(getMethodThrows()); 889 890 return buff.toString(); 891 } 892 893 private String getVisibilityString(int visibility) { 894 String visibilityString= JdtFlags.getVisibilityString(visibility); 895 if ("".equals(visibilityString)) return visibilityString; 897 return visibilityString + ' '; 898 } 899 900 private String getMethodThrows() { 901 final String throwsString= " throws "; StringBuffer buff= new StringBuffer (throwsString); 903 for (Iterator iter= fExceptionInfos.iterator(); iter.hasNext(); ) { 904 ExceptionInfo info= (ExceptionInfo) iter.next(); 905 if (! info.isDeleted()) { 906 buff.append(info.getType().getElementName()); 907 buff.append(", "); } 909 } 910 if (buff.length() == throwsString.length()) 911 return ""; buff.delete(buff.length() - 2, buff.length()); 913 return buff.toString(); 914 } 915 916 private String getOldMethodThrows() { 917 final String throwsString= " throws "; StringBuffer buff= new StringBuffer (throwsString); 919 for (Iterator iter= fExceptionInfos.iterator(); iter.hasNext(); ) { 920 ExceptionInfo info= (ExceptionInfo) iter.next(); 921 if (! info.isAdded()) { 922 buff.append(info.getType().getElementName()); 923 buff.append(", "); } 925 } 926 if (buff.length() == throwsString.length()) 927 return ""; buff.delete(buff.length() - 2, buff.length()); 929 return buff.toString(); 930 } 931 932 private void checkForDuplicateParameterNames(RefactoringStatus result){ 933 Set found= new HashSet (); 934 Set doubled= new HashSet (); 935 for (Iterator iter = getNotDeletedInfos().iterator(); iter.hasNext();) { 936 ParameterInfo info= (ParameterInfo)iter.next(); 937 String newName= info.getNewName(); 938 if (found.contains(newName) && !doubled.contains(newName)){ 939 result.addFatalError(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_duplicate_name, newName)); 940 doubled.add(newName); 941 } else { 942 found.add(newName); 943 } 944 } 945 } 946 947 private ICompilationUnit getCu() { 948 return fMethod.getCompilationUnit(); 949 } 950 951 private boolean mustAnalyzeAstOfDeclaringCu() throws JavaModelException{ 952 if (JdtFlags.isAbstract(getMethod())) 953 return false; 954 else if (JdtFlags.isNative(getMethod())) 955 return false; 956 else if (getMethod().getDeclaringType().isInterface()) 957 return false; 958 else 959 return true; 960 } 961 962 private RefactoringStatus checkCompilationofDeclaringCu() throws CoreException { 963 ICompilationUnit cu= getCu(); 964 TextChange change= fChangeManager.get(cu); 965 String newCuSource= change.getPreviewContent(new NullProgressMonitor()); 966 CompilationUnit newCUNode= new RefactoringASTParser(AST.JLS3).parse(newCuSource, cu, true, false, null); 967 IProblem[] problems= RefactoringAnalyzeUtil.getIntroducedCompileProblems(newCUNode, fBaseCuRewrite.getRoot()); 968 RefactoringStatus result= new RefactoringStatus(); 969 for (int i= 0; i < problems.length; i++) { 970 IProblem problem= problems[i]; 971 if (shouldReport(problem, newCUNode)) 972 result.addEntry(new RefactoringStatusEntry((problem.isError() ? RefactoringStatus.ERROR : RefactoringStatus.WARNING), problem.getMessage(), new JavaStringStatusContext(newCuSource, new SourceRange(problem)))); 973 } 974 return result; 975 } 976 977 private boolean shouldReport(IProblem problem, CompilationUnit cu) { 978 if (! problem.isError()) 979 return false; 980 if (problem.getID() == IProblem.UndefinedType) return false; 982 ASTNode node= ASTNodeSearchUtil.getAstNode(cu, problem.getSourceStart(), problem.getSourceEnd() - problem.getSourceStart()); 983 IProblemVerifier verifier= doGetProblemVerifier(); 984 if (verifier != null) 985 return verifier.isError(problem, node); 986 return true; 987 } 988 989 private String getOldMethodParameters() { 990 StringBuffer buff= new StringBuffer (); 991 int i= 0; 992 for (Iterator iter= getNotAddedInfos().iterator(); iter.hasNext(); i++) { 993 ParameterInfo info= (ParameterInfo) iter.next(); 994 if (i != 0 ) 995 buff.append(", "); buff.append(createDeclarationString(info)); 997 } 998 return buff.toString(); 999 } 1000 1001 private String getMethodParameters() { 1002 StringBuffer buff= new StringBuffer (); 1003 int i= 0; 1004 for (Iterator iter= getNotDeletedInfos().iterator(); iter.hasNext(); i++) { 1005 ParameterInfo info= (ParameterInfo) iter.next(); 1006 if (i != 0 ) 1007 buff.append(", "); buff.append(createDeclarationString(info)); 1009 } 1010 return buff.toString(); 1011 } 1012 1013 private List getAddedInfos(){ 1014 List result= new ArrayList (1); 1015 for (Iterator iter= fParameterInfos.iterator(); iter.hasNext();) { 1016 ParameterInfo info= (ParameterInfo) iter.next(); 1017 if (info.isAdded()) 1018 result.add(info); 1019 } 1020 return result; 1021 } 1022 1023 private List getDeletedInfos(){ 1024 List result= new ArrayList (1); 1025 for (Iterator iter= fParameterInfos.iterator(); iter.hasNext();) { 1026 ParameterInfo info= (ParameterInfo) iter.next(); 1027 if (info.isDeleted()) 1028 result.add(info); 1029 } 1030 return result; 1031 } 1032 1033 private List getNotAddedInfos(){ 1034 List all= new ArrayList (fParameterInfos); 1035 all.removeAll(getAddedInfos()); 1036 return all; 1037 } 1038 1039 private List getNotDeletedInfos(){ 1040 List all= new ArrayList (fParameterInfos); 1041 all.removeAll(getDeletedInfos()); 1042 return all; 1043 } 1044 1045 private boolean areNamesSameAsInitial() { 1046 for (Iterator iter= fParameterInfos.iterator(); iter.hasNext();) { 1047 ParameterInfo info= (ParameterInfo) iter.next(); 1048 if (info.isRenamed()) 1049 return false; 1050 } 1051 return true; 1052 } 1053 1054 private boolean isOrderSameAsInitial(){ 1055 int i= 0; 1056 for (Iterator iter= fParameterInfos.iterator(); iter.hasNext(); i++) { 1057 ParameterInfo info= (ParameterInfo) iter.next(); 1058 if (info.getOldIndex() != i) return false; 1060 if (info.isDeleted()) 1061 return false; 1062 } 1063 return true; 1064 } 1065 1066 private RefactoringStatus checkReorderings(IProgressMonitor pm) throws JavaModelException { 1067 try{ 1068 pm.beginTask(RefactoringCoreMessages.ChangeSignatureRefactoring_checking_preconditions, 1); 1069 return checkNativeMethods(); 1070 } finally{ 1071 pm.done(); 1072 } 1073 } 1074 1075 private RefactoringStatus checkRenamings(IProgressMonitor pm) throws JavaModelException { 1076 try{ 1077 pm.beginTask(RefactoringCoreMessages.ChangeSignatureRefactoring_checking_preconditions, 1); 1078 return checkParameterNamesInRippleMethods(); 1079 } finally{ 1080 pm.done(); 1081 } 1082 } 1083 1084 private RefactoringStatus checkParameterNamesInRippleMethods() throws JavaModelException { 1085 RefactoringStatus result= new RefactoringStatus(); 1086 Set newParameterNames= getNewParameterNamesList(); 1087 for (int i= 0; i < fRippleMethods.length; i++) { 1088 String [] paramNames= fRippleMethods[i].getParameterNames(); 1089 for (int j= 0; j < paramNames.length; j++) { 1090 if (newParameterNames.contains(paramNames[j])){ 1091 String [] args= new String []{JavaElementUtil.createMethodSignature(fRippleMethods[i]), paramNames[j]}; 1092 String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_already_has, args); 1093 RefactoringStatusContext context= JavaStatusContext.create(fRippleMethods[i].getCompilationUnit(), fRippleMethods[i].getNameRange()); 1094 result.addError(msg, context); 1095 } 1096 } 1097 } 1098 return result; 1099 } 1100 1101 private Set getNewParameterNamesList() { 1102 Set oldNames= getOriginalParameterNames(); 1103 Set currentNames= getNamesOfNotDeletedParameters(); 1104 currentNames.removeAll(oldNames); 1105 return currentNames; 1106 } 1107 1108 private Set getNamesOfNotDeletedParameters() { 1109 Set result= new HashSet (); 1110 for (Iterator iter= getNotDeletedInfos().iterator(); iter.hasNext();) { 1111 ParameterInfo info= (ParameterInfo) iter.next(); 1112 result.add(info.getNewName()); 1113 } 1114 return result; 1115 } 1116 1117 private Set getOriginalParameterNames() { 1118 Set result= new HashSet (); 1119 for (Iterator iter= fParameterInfos.iterator(); iter.hasNext();) { 1120 ParameterInfo info= (ParameterInfo) iter.next(); 1121 if (! info.isAdded()) 1122 result.add(info.getOldName()); 1123 } 1124 return result; 1125 } 1126 1127 private RefactoringStatus checkNativeMethods() throws JavaModelException{ 1128 RefactoringStatus result= new RefactoringStatus(); 1129 for (int i= 0; i < fRippleMethods.length; i++) { 1130 if (JdtFlags.isNative(fRippleMethods[i])){ 1131 String message= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_native, 1132 new String []{JavaElementUtil.createMethodSignature(fRippleMethods[i]), JavaModelUtil.getFullyQualifiedName(fRippleMethods[i].getDeclaringType())}); 1133 result.addError(message, JavaStatusContext.create(fRippleMethods[i])); 1134 } 1135 } 1136 return result; 1137 } 1138 1139 private IFile[] getAllFilesToModify(){ 1140 return ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits()); 1141 } 1142 1143 private RefactoringStatus validateModifiesFiles(){ 1144 return Checks.validateModifiesFiles(getAllFilesToModify(), getValidationContext()); 1145 } 1146 1147 public Change createChange(IProgressMonitor pm) { 1148 pm.beginTask("", 1); try { 1150 final TextChange[] changes= fChangeManager.getAllChanges(); 1151 final List list= new ArrayList (changes.length); 1152 list.addAll(fOtherChanges); 1153 list.addAll(Arrays.asList(changes)); 1154 final Map arguments= new HashMap (); 1155 String project= null; 1156 IJavaProject javaProject= fMethod.getJavaProject(); 1157 if (javaProject != null) 1158 project= javaProject.getElementName(); 1159 int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE; 1160 try { 1161 if (!Flags.isPrivate(fMethod.getFlags())) 1162 flags|= RefactoringDescriptor.MULTI_CHANGE; 1163 final IType declaring= fMethod.getDeclaringType(); 1164 if (declaring.isAnonymous() || declaring.isLocal()) 1165 flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT; 1166 } catch (JavaModelException exception) { 1167 JavaPlugin.log(exception); 1168 } 1169 JDTRefactoringDescriptor descriptor= null; 1170 try { 1171 final String description= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_descriptor_description_short, fMethod.getElementName()); 1172 final String header= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_descriptor_description, new String [] { getOldMethodSignature(), getNewMethodSignature()}); 1173 final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header); 1174 if (!fMethod.getElementName().equals(fMethodName)) 1175 comment.addSetting(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_new_name_pattern, fMethodName)); 1176 if (!isVisibilitySameAsInitial()) { 1177 String visibility= JdtFlags.getVisibilityString(fVisibility); 1178 if ("".equals(visibility)) visibility= RefactoringCoreMessages.ChangeSignatureRefactoring_default_visibility; 1180 comment.addSetting(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_new_visibility_pattern, visibility)); 1181 } 1182 if (fReturnTypeInfo.isTypeNameChanged()) 1183 comment.addSetting(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_new_return_type_pattern, fReturnTypeInfo.getNewTypeName())); 1184 List deleted= new ArrayList (); 1185 List added= new ArrayList (); 1186 List changed= new ArrayList (); 1187 for (final Iterator iterator= fParameterInfos.iterator(); iterator.hasNext();) { 1188 final ParameterInfo info= (ParameterInfo) iterator.next(); 1189 if (info.isDeleted()) 1190 deleted.add(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_deleted_parameter_pattern, new String [] { info.getOldTypeName(), info.getOldName()})); 1191 else if (info.isAdded()) 1192 added.add(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_added_parameter_pattern, new String [] { info.getNewTypeName(), info.getNewName()})); 1193 else if (info.isRenamed() || info.isTypeNameChanged() || info.isVarargChanged()) 1194 changed.add(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_changed_parameter_pattern, new String [] { info.getOldTypeName(), info.getOldName()})); 1195 } 1196 if (!added.isEmpty()) 1197 comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_added_parameters, (String []) added.toArray(new String [added.size()]))); 1198 if (!deleted.isEmpty()) 1199 comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_removed_parameters, (String []) deleted.toArray(new String [deleted.size()]))); 1200 if (!changed.isEmpty()) 1201 comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_changed_parameters, (String []) changed.toArray(new String [changed.size()]))); 1202 added.clear(); 1203 deleted.clear(); 1204 changed.clear(); 1205 for (final Iterator iterator= fExceptionInfos.iterator(); iterator.hasNext();) { 1206 final ExceptionInfo info= (ExceptionInfo) iterator.next(); 1207 if (info.isAdded()) 1208 added.add(info.getType().getElementName()); 1209 else if (info.isDeleted()) 1210 deleted.add(info.getType().getElementName()); 1211 } 1212 if (!added.isEmpty()) 1213 comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_added_exceptions, (String []) added.toArray(new String [added.size()]))); 1214 if (!deleted.isEmpty()) 1215 comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_removed_exceptions, (String []) deleted.toArray(new String [deleted.size()]))); 1216 descriptor= new JDTRefactoringDescriptor(IJavaRefactorings.CHANGE_METHOD_SIGNATURE, project, description, comment.asString(), arguments, flags); 1217 arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_INPUT, descriptor.elementToHandle(fMethod)); 1218 arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_NAME, fMethodName); 1219 arguments.put(ATTRIBUTE_DELEGATE, Boolean.valueOf(fDelegateUpdating).toString()); 1220 arguments.put(ATTRIBUTE_DEPRECATE, Boolean.valueOf(fDelegateDeprecation).toString()); 1221 if (fReturnTypeInfo.isTypeNameChanged()) 1222 arguments.put(ATTRIBUTE_RETURN, fReturnTypeInfo.getNewTypeName()); 1223 try { 1224 if (!isVisibilitySameAsInitial()) 1225 arguments.put(ATTRIBUTE_VISIBILITY, new Integer (fVisibility).toString()); 1226 } catch (JavaModelException exception) { 1227 JavaPlugin.log(exception); 1228 } 1229 int count= 1; 1230 for (final Iterator iterator= fParameterInfos.iterator(); iterator.hasNext();) { 1231 final ParameterInfo info= (ParameterInfo) iterator.next(); 1232 final StringBuffer buffer= new StringBuffer (64); 1233 buffer.append(info.getOldTypeName()); 1234 buffer.append(" "); buffer.append(info.getOldName()); 1236 buffer.append(" "); buffer.append(info.getOldIndex()); 1238 buffer.append(" "); buffer.append(info.getNewTypeName()); 1240 buffer.append(" "); buffer.append(info.getNewName()); 1242 buffer.append(" "); buffer.append(info.isDeleted()); 1244 arguments.put(ATTRIBUTE_PARAMETER + count, buffer.toString()); 1245 final String value= info.getDefaultValue(); 1246 if (value != null && !"".equals(value)) arguments.put(ATTRIBUTE_DEFAULT + count, value); 1248 count++; 1249 } 1250 count= 1; 1251 for (final Iterator iterator= fExceptionInfos.iterator(); iterator.hasNext();) { 1252 final ExceptionInfo info= (ExceptionInfo) iterator.next(); 1253 arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + count, descriptor.elementToHandle(info.getType())); 1254 arguments.put(ATTRIBUTE_KIND + count, new Integer (info.getKind()).toString()); 1255 count++; 1256 } 1257 } catch (JavaModelException exception) { 1258 JavaPlugin.log(exception); 1259 return null; 1260 } 1261 return new DynamicValidationRefactoringChange(descriptor, doGetRefactoringChangeName(), (Change[]) list.toArray(new Change[list.size()])); 1262 } finally { 1263 pm.done(); 1264 clearManagers(); 1265 } 1266 } 1267 1268 protected String doGetRefactoringChangeName() { 1269 return RefactoringCoreMessages.ChangeSignatureRefactoring_restructure_parameters; 1270 } 1271 1272 private TextChangeManager createChangeManager(IProgressMonitor pm, RefactoringStatus result) throws CoreException { 1273 pm.beginTask(RefactoringCoreMessages.ChangeSignatureRefactoring_preview, 2); 1274 fChangeManager= new TextChangeManager(); 1275 boolean isNoArgConstructor= isNoArgConstructor(); 1276 Map namedSubclassMapping= null; 1277 if (isNoArgConstructor){ 1278 namedSubclassMapping= createNamedSubclassMapping(new SubProgressMonitor(pm, 1)); 1280 }else{ 1281 pm.worked(1); 1282 } 1283 for (int i= 0; i < fOccurrences.length; i++) { 1284 if (pm.isCanceled()) 1285 throw new OperationCanceledException(); 1286 SearchResultGroup group= fOccurrences[i]; 1287 ICompilationUnit cu= group.getCompilationUnit(); 1288 if (cu == null) 1289 continue; 1290 CompilationUnitRewrite cuRewrite; 1291 if (cu.equals(getCu())) { 1292 cuRewrite= fBaseCuRewrite; 1293 } else { 1294 cuRewrite= new CompilationUnitRewrite(cu); 1295 cuRewrite.getASTRewrite().setTargetSourceRangeComputer(new TightSourceRangeComputer()); 1296 } 1297 ASTNode[] nodes= ASTNodeSearchUtil.findNodes(group.getSearchResults(), cuRewrite.getRoot()); 1298 1299 List deferredUpdates= new ArrayList (); 1301 for (int j= 0; j < nodes.length; j++) { 1302 OccurrenceUpdate update= createOccurrenceUpdate(nodes[j], cuRewrite, result); 1303 if (update instanceof DeclarationUpdate) { 1304 update.updateNode(); 1305 } else { 1306 deferredUpdates.add(update); 1307 } 1308 } 1309 for (Iterator iter= deferredUpdates.iterator(); iter.hasNext();) { 1310 ((OccurrenceUpdate) iter.next()).updateNode(); 1311 } 1312 1313 if (isNoArgConstructor && namedSubclassMapping.containsKey(cu)){ 1314 Set subtypes= (Set )namedSubclassMapping.get(cu); 1316 for (Iterator iter= subtypes.iterator(); iter.hasNext();) { 1317 IType subtype= (IType) iter.next(); 1318 AbstractTypeDeclaration subtypeNode= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(subtype, cuRewrite.getRoot()); 1319 if (subtypeNode != null) 1320 modifyImplicitCallsToNoArgConstructor(subtypeNode, cuRewrite); 1321 } 1322 } 1323 TextChange change= cuRewrite.createChange(); 1324 if (change != null) 1325 fChangeManager.manage(cu, change); 1326 } 1327 1328 pm.done(); 1329 return fChangeManager; 1330 } 1331 1332 private Map createNamedSubclassMapping(IProgressMonitor pm) throws JavaModelException{ 1334 IType[] subclasses= getCachedTypeHierarchy(new SubProgressMonitor(pm, 1)).getSubclasses(fMethod.getDeclaringType()); 1335 Map result= new HashMap (); 1336 for (int i= 0; i < subclasses.length; i++) { 1337 IType subclass= subclasses[i]; 1338 if (subclass.isAnonymous()) 1339 continue; 1340 ICompilationUnit cu= subclass.getCompilationUnit(); 1341 if (! result.containsKey(cu)) 1342 result.put(cu, new HashSet ()); 1343 ((Set )result.get(cu)).add(subclass); 1344 } 1345 return result; 1346 } 1347 1348 private void modifyImplicitCallsToNoArgConstructor(AbstractTypeDeclaration subclass, CompilationUnitRewrite cuRewrite) { 1349 MethodDeclaration[] constructors= getAllConstructors(subclass); 1350 if (constructors.length == 0){ 1351 addNewConstructorToSubclass(subclass, cuRewrite); 1352 } else { 1353 for (int i= 0; i < constructors.length; i++) { 1354 if (! containsImplicitCallToSuperConstructor(constructors[i])) 1355 continue; 1356 addExplicitSuperConstructorCall(constructors[i], cuRewrite); 1357 } 1358 } 1359 } 1360 1361 private void addExplicitSuperConstructorCall(MethodDeclaration constructor, CompilationUnitRewrite cuRewrite) { 1362 SuperConstructorInvocation superCall= constructor.getAST().newSuperConstructorInvocation(); 1363 addArgumentsToNewSuperConstructorCall(superCall, cuRewrite); 1364 String msg= RefactoringCoreMessages.ChangeSignatureRefactoring_add_super_call; 1365 TextEditGroup description= cuRewrite.createGroupDescription(msg); 1366 cuRewrite.getASTRewrite().getListRewrite(constructor.getBody(), Block.STATEMENTS_PROPERTY).insertFirst(superCall, description); 1367 } 1368 1369 private void addArgumentsToNewSuperConstructorCall(SuperConstructorInvocation superCall, CompilationUnitRewrite cuRewrite) { 1370 int i= 0; 1371 for (Iterator iter= getNotDeletedInfos().iterator(); iter.hasNext(); i++) { 1372 ParameterInfo info= (ParameterInfo) iter.next(); 1373 Expression newExpression= createNewExpression(info, getParameterInfos(), superCall.arguments(), cuRewrite, (MethodDeclaration) ASTNodes.getParent(superCall, MethodDeclaration.class)); 1374 if (newExpression != null) 1375 superCall.arguments().add(newExpression); 1376 } 1377 } 1378 1379 private static boolean containsImplicitCallToSuperConstructor(MethodDeclaration constructor) { 1380 Assert.isTrue(constructor.isConstructor()); 1381 Block body= constructor.getBody(); 1382 if (body == null) 1383 return false; 1384 if (body.statements().size() == 0) 1385 return true; 1386 if (body.statements().get(0) instanceof ConstructorInvocation) 1387 return false; 1388 if (body.statements().get(0) instanceof SuperConstructorInvocation) 1389 return false; 1390 return true; 1391 } 1392 1393 private void addNewConstructorToSubclass(AbstractTypeDeclaration subclass, CompilationUnitRewrite cuRewrite) { 1394 AST ast= subclass.getAST(); 1395 MethodDeclaration newConstructor= ast.newMethodDeclaration(); 1396 newConstructor.setName(ast.newSimpleName(subclass.getName().getIdentifier())); 1397 newConstructor.setConstructor(true); 1398 newConstructor.setExtraDimensions(0); 1399 newConstructor.setJavadoc(null); 1400 newConstructor.modifiers().addAll(ASTNodeFactory.newModifiers(ast, getAccessModifier(subclass))); 1401 newConstructor.setReturnType2(ast.newPrimitiveType(PrimitiveType.VOID)); 1402 Block body= ast.newBlock(); 1403 newConstructor.setBody(body); 1404 SuperConstructorInvocation superCall= ast.newSuperConstructorInvocation(); 1405 addArgumentsToNewSuperConstructorCall(superCall, cuRewrite); 1406 body.statements().add(superCall); 1407 1408 String msg= RefactoringCoreMessages.ChangeSignatureRefactoring_add_constructor; 1409 TextEditGroup description= cuRewrite.createGroupDescription(msg); 1410 cuRewrite.getASTRewrite().getListRewrite(subclass, subclass.getBodyDeclarationsProperty()).insertFirst(newConstructor, description); 1411 1412 } 1414 1415 private static int getAccessModifier(AbstractTypeDeclaration subclass) { 1416 int modifiers= subclass.getModifiers(); 1417 if (Modifier.isPublic(modifiers)) 1418 return Modifier.PUBLIC; 1419 else if (Modifier.isProtected(modifiers)) 1420 return Modifier.PROTECTED; 1421 else if (Modifier.isPrivate(modifiers)) 1422 return Modifier.PRIVATE; 1423 else 1424 return Modifier.NONE; 1425 } 1426 1427 private MethodDeclaration[] getAllConstructors(AbstractTypeDeclaration typeDeclaration) { 1428 BodyDeclaration decl; 1429 List result= new ArrayList (1); 1430 for (Iterator it = typeDeclaration.bodyDeclarations().listIterator(); it.hasNext(); ) { 1431 decl= (BodyDeclaration) it.next(); 1432 if (decl instanceof MethodDeclaration && ((MethodDeclaration) decl).isConstructor()) 1433 result.add(decl); 1434 } 1435 return (MethodDeclaration[]) result.toArray(new MethodDeclaration[result.size()]); 1436 } 1437 1438 private boolean isNoArgConstructor() throws JavaModelException { 1439 return fMethod.isConstructor() && fMethod.getNumberOfParameters() == 0; 1440 } 1441 1442 private Expression createNewExpression(ParameterInfo info, List parameterInfos, List nodes, CompilationUnitRewrite cuRewrite, MethodDeclaration method) { 1443 if (info.isNewVarargs() && info.getDefaultValue().trim().length() == 0) 1444 return null; 1445 else { 1446 if (fDefaultValueAdvisor == null) 1447 return (Expression) cuRewrite.getASTRewrite().createStringPlaceholder(info.getDefaultValue(), ASTNode.METHOD_INVOCATION); 1448 else 1449 return fDefaultValueAdvisor.createDefaultExpression(nodes, info, parameterInfos, method, false, cuRewrite); 1450 } 1451 } 1452 1453 private boolean isVisibilitySameAsInitial() throws JavaModelException { 1454 return fVisibility == JdtFlags.getVisibilityCode(fMethod); 1455 } 1456 1457 private IJavaSearchScope createRefactoringScope() throws JavaModelException{ 1458 return RefactoringScopeFactory.create(fMethod); 1459 } 1460 1461 private SearchResultGroup[] findOccurrences(IProgressMonitor pm, RefactoringStatus status) throws JavaModelException{ 1462 if (fMethod.isConstructor()){ 1463 return ConstructorReferenceFinder.getConstructorOccurrences(fMethod, pm, status); 1465 }else{ 1466 SearchPattern pattern= RefactoringSearchEngine.createOrPattern(fRippleMethods, IJavaSearchConstants.ALL_OCCURRENCES); 1467 return RefactoringSearchEngine.search(pattern, createRefactoringScope(), pm, status); 1468 } 1469 } 1470 1471 private static String createDeclarationString(ParameterInfo info) { 1472 String newTypeName= info.getNewTypeName(); 1473 int index= newTypeName.indexOf('.'); 1474 if (index != -1){ 1475 newTypeName= newTypeName.substring(index+1); 1476 } 1477 return newTypeName + " " + info.getNewName(); } 1479 1480 private static final boolean BUG_89686= true; 1482 private OccurrenceUpdate createOccurrenceUpdate(ASTNode node, CompilationUnitRewrite cuRewrite, RefactoringStatus result) { 1483 if (BUG_89686 && node instanceof SimpleName && node.getParent() instanceof EnumConstantDeclaration) 1484 node= node.getParent(); 1485 1486 if (isReferenceNode(node)) 1487 return new ReferenceUpdate(node, cuRewrite, result); 1488 1489 else if (node instanceof SimpleName && node.getParent() instanceof MethodDeclaration) 1490 return new DeclarationUpdate((MethodDeclaration) node.getParent(), cuRewrite, result); 1491 1492 else if (node instanceof MemberRef || node instanceof MethodRef) 1493 return new DocReferenceUpdate(node, cuRewrite, result); 1494 1495 else if (ASTNodes.getParent(node, ImportDeclaration.class) != null) 1496 return new StaticImportUpdate((ImportDeclaration) ASTNodes.getParent(node, ImportDeclaration.class), cuRewrite, result); 1497 1498 else 1499 return new NullOccurrenceUpdate(node, cuRewrite, result); 1500 } 1501 1502 private static boolean isReferenceNode(ASTNode node){ 1503 switch (node.getNodeType()) { 1504 case ASTNode.METHOD_INVOCATION : 1505 case ASTNode.SUPER_METHOD_INVOCATION : 1506 case ASTNode.CLASS_INSTANCE_CREATION : 1507 case ASTNode.CONSTRUCTOR_INVOCATION : 1508 case ASTNode.SUPER_CONSTRUCTOR_INVOCATION : 1509 case ASTNode.ENUM_CONSTANT_DECLARATION : 1510 return true; 1511 1512 default : 1513 return false; 1514 } 1515 } 1516 1517 abstract class OccurrenceUpdate { 1518 protected final CompilationUnitRewrite fCuRewrite; 1519 protected final TextEditGroup fDescription; 1520 protected RefactoringStatus fResult; 1521 1522 protected OccurrenceUpdate(CompilationUnitRewrite cuRewrite, TextEditGroup description, RefactoringStatus result) { 1523 fCuRewrite= cuRewrite; 1524 fDescription= description; 1525 fResult= result; 1526 } 1527 1528 protected final ASTRewrite getASTRewrite() { 1529 return fCuRewrite.getASTRewrite(); 1530 } 1531 1532 protected final ImportRewrite getImportRewrite() { 1533 return fCuRewrite.getImportRewrite(); 1534 } 1535 1536 protected final ImportRemover getImportRemover() { 1537 return fCuRewrite.getImportRemover(); 1538 } 1539 1540 protected final CompilationUnitRewrite getCompilationUnitRewrite() { 1541 return fCuRewrite; 1542 } 1543 1544 public abstract void updateNode() throws CoreException; 1545 1546 protected void registerImportRemoveNode(ASTNode node) { 1547 getImportRemover().registerRemovedNode(node); 1548 } 1549 1550 protected final void reshuffleElements() { 1551 if (isOrderSameAsInitial()) 1552 return; 1553 1554 1578 ListRewrite listRewrite= getParamgumentsRewrite(); 1579 Map newOldMap= new LinkedHashMap (); 1580 List nodes= listRewrite.getRewrittenList(); 1581 Iterator rewriteIter= nodes.iterator(); 1582 List original= listRewrite.getOriginalList(); 1583 for (Iterator iter= original.iterator(); iter.hasNext();) { 1584 newOldMap.put(rewriteIter.next(),iter.next()); 1585 } 1586 List newNodes= new ArrayList (); 1587 for (int i= 0; i < fParameterInfos.size(); i++) { 1589 ParameterInfo info= (ParameterInfo) fParameterInfos.get(i); 1590 int oldIndex= info.getOldIndex(); 1591 1592 if (info.isDeleted()) { 1593 if (oldIndex != fOldVarargIndex) { 1594 registerImportRemoveNode((ASTNode) nodes.get(oldIndex)); 1595 } else { 1596 for (int n= oldIndex; n < nodes.size(); n++) { 1598 registerImportRemoveNode((ASTNode) nodes.get(n)); 1599 } 1600 } 1601 1602 } else if (info.isAdded()) { 1603 ASTNode newParamgument= createNewParamgument(info, fParameterInfos, nodes); 1604 if (newParamgument != null) 1605 newNodes.add(newParamgument); 1606 1607 } else { 1608 if (oldIndex != fOldVarargIndex) { 1609 ASTNode oldNode= (ASTNode) nodes.get(oldIndex); 1610 ASTNode movedNode= moveNode(oldNode, getASTRewrite()); 1611 newNodes.add(movedNode); 1612 } else { 1613 for (int n= oldIndex; n < nodes.size(); n++) { 1615 ASTNode oldNode= (ASTNode) nodes.get(n); 1616 ASTNode movedNode= moveNode(oldNode, getASTRewrite()); 1617 newNodes.add(movedNode); 1618 } 1619 } 1620 } 1621 } 1622 1623 Iterator nodesIter= nodes.iterator(); 1624 Iterator newIter= newNodes.iterator(); 1625 while (nodesIter.hasNext() && newIter.hasNext()) { 1627 ASTNode node= (ASTNode) nodesIter.next(); 1628 ASTNode newNode= (ASTNode) newIter.next(); 1629 if (!ASTNodes.isExistingNode(node)) listRewrite.replace((ASTNode) newOldMap.get(node), newNode, fDescription); 1631 else 1632 listRewrite.replace(node, newNode, fDescription); 1633 } 1634 while (nodesIter.hasNext()) { 1636 ASTNode node= (ASTNode) nodesIter.next(); 1637 if (!ASTNodes.isExistingNode(node)) 1638 listRewrite.remove((ASTNode) newOldMap.get(node), fDescription); 1639 else 1640 listRewrite.remove(node, fDescription); 1641 } 1642 while (newIter.hasNext()) { 1644 ASTNode node= (ASTNode) newIter.next(); 1645 listRewrite.insertLast(node, fDescription); 1646 } 1647 } 1648 1649 1652 protected abstract ListRewrite getParamgumentsRewrite(); 1653 1654 protected final void changeParamguments() { 1655 for (Iterator iter= getParameterInfos().iterator(); iter.hasNext();) { 1656 ParameterInfo info= (ParameterInfo) iter.next(); 1657 if (info.isAdded() || info.isDeleted()) 1658 continue; 1659 1660 if (info.isRenamed()) 1661 changeParamgumentName(info); 1662 1663 if (info.isTypeNameChanged()) 1664 changeParamgumentType(info); 1665 } 1666 } 1667 1668 protected void changeParamgumentName(ParameterInfo info) { 1669 } 1671 1672 protected void changeParamgumentType(ParameterInfo info) { 1673 } 1675 1676 protected final void replaceTypeNode(Type typeNode, String newTypeName, ITypeBinding newTypeBinding){ 1677 Type newTypeNode= createNewTypeNode(newTypeName, newTypeBinding); 1678 getASTRewrite().replace(typeNode, newTypeNode, fDescription); 1679 registerImportRemoveNode(typeNode); 1680 getTightSourceRangeComputer().addTightSourceNode(typeNode); 1681 } 1682 1683 1689 protected abstract ASTNode createNewParamgument(ParameterInfo info, List parameterInfos, List nodes); 1690 1691 protected abstract SimpleName getMethodNameNode(); 1692 1693 protected final void changeMethodName() { 1694 if (! isMethodNameSameAsInitial()) { 1695 SimpleName nameNode= getMethodNameNode(); 1696 SimpleName newNameNode= nameNode.getAST().newSimpleName(fMethodName); 1697 getASTRewrite().replace(nameNode, newNameNode, fDescription); 1698 registerImportRemoveNode(nameNode); 1699 getTightSourceRangeComputer().addTightSourceNode(nameNode); 1700 } 1701 } 1702 1703 protected final Type createNewTypeNode(String newTypeName, ITypeBinding newTypeBinding) { 1704 Type newTypeNode; 1705 if (newTypeBinding == null) { 1706 if (fDefaultValueAdvisor != null) 1707 newTypeNode= fDefaultValueAdvisor.createType(newTypeName, getMethodNameNode().getStartPosition(), getCompilationUnitRewrite()); 1708 else 1709 newTypeNode= (Type) getASTRewrite().createStringPlaceholder(newTypeName, ASTNode.SIMPLE_TYPE); 1710 } else { 1712 newTypeNode= getImportRewrite().addImport(newTypeBinding, fCuRewrite.getAST()); 1713 getImportRemover().registerAddedImports(newTypeNode); 1714 } 1715 return newTypeNode; 1716 } 1717 1718 protected final TightSourceRangeComputer getTightSourceRangeComputer() { 1719 return (TightSourceRangeComputer) fCuRewrite.getASTRewrite().getExtendedSourceRangeComputer(); 1720 } 1721 } 1722 1723 class ReferenceUpdate extends OccurrenceUpdate { 1724 1725 private ASTNode fNode; 1726 1727 protected ReferenceUpdate(ASTNode node, CompilationUnitRewrite cuRewrite, RefactoringStatus result) { 1728 super(cuRewrite, cuRewrite.createGroupDescription(RefactoringCoreMessages.ChangeSignatureRefactoring_update_reference), result); 1729 fNode= node; } 1731 1732 public void updateNode() { 1733 reshuffleElements(); 1734 changeMethodName(); 1735 } 1736 1737 1738 protected ListRewrite getParamgumentsRewrite() { 1739 if (fNode instanceof MethodInvocation) 1740 return getASTRewrite().getListRewrite(fNode, MethodInvocation.ARGUMENTS_PROPERTY); 1741 1742 if (fNode instanceof SuperMethodInvocation) 1743 return getASTRewrite().getListRewrite(fNode, SuperMethodInvocation.ARGUMENTS_PROPERTY); 1744 1745 if (fNode instanceof ClassInstanceCreation) 1746 return getASTRewrite().getListRewrite(fNode, ClassInstanceCreation.ARGUMENTS_PROPERTY); 1747 1748 if (fNode instanceof ConstructorInvocation) 1749 return getASTRewrite().getListRewrite(fNode, ConstructorInvocation.ARGUMENTS_PROPERTY); 1750 1751 if (fNode instanceof SuperConstructorInvocation) 1752 return getASTRewrite().getListRewrite(fNode, SuperConstructorInvocation.ARGUMENTS_PROPERTY); 1753 1754 if (fNode instanceof EnumConstantDeclaration) 1755 return getASTRewrite().getListRewrite(fNode, EnumConstantDeclaration.ARGUMENTS_PROPERTY); 1756 1757 return null; 1758 } 1759 1760 protected ASTNode createNewParamgument(ParameterInfo info, List parameterInfos, List nodes) { 1761 CompilationUnitRewrite cuRewrite= getCompilationUnitRewrite(); 1762 MethodDeclaration declaration= (MethodDeclaration) ASTNodes.getParent(fNode, MethodDeclaration.class); 1763 if (isRecursiveReference()) { 1764 return createNewExpressionRecursive(info, parameterInfos, nodes, cuRewrite, declaration); 1765 } else 1766 return createNewExpression(info, parameterInfos, nodes, cuRewrite, declaration); 1767 } 1768 1769 private Expression createNewExpressionRecursive(ParameterInfo info, List parameterInfos, List nodes, CompilationUnitRewrite cuRewrite, MethodDeclaration methodDeclaration) { 1770 if (fDefaultValueAdvisor != null && info.isAdded()) { 1771 return fDefaultValueAdvisor.createDefaultExpression(nodes, info, parameterInfos, methodDeclaration, true, cuRewrite); 1772 } 1773 return (Expression) getASTRewrite().createStringPlaceholder(info.getNewName(), ASTNode.METHOD_INVOCATION); 1774 } 1775 1776 protected SimpleName getMethodNameNode() { 1777 if (fNode instanceof MethodInvocation) 1778 return ((MethodInvocation)fNode).getName(); 1779 1780 if (fNode instanceof SuperMethodInvocation) 1781 return ((SuperMethodInvocation)fNode).getName(); 1782 1783 return null; 1784 } 1785 1786 private boolean isRecursiveReference() { 1787 MethodDeclaration enclosingMethodDeclaration= (MethodDeclaration) ASTNodes.getParent(fNode, MethodDeclaration.class); 1788 if (enclosingMethodDeclaration == null) 1789 return false; 1790 1791 IMethodBinding enclosingMethodBinding= enclosingMethodDeclaration.resolveBinding(); 1792 if (enclosingMethodBinding == null) 1793 return false; 1794 1795 if (fNode instanceof MethodInvocation) 1796 return enclosingMethodBinding == ((MethodInvocation)fNode).resolveMethodBinding(); 1797 1798 if (fNode instanceof SuperMethodInvocation) { 1799 IMethodBinding methodBinding= ((SuperMethodInvocation)fNode).resolveMethodBinding(); 1800 return isSameMethod(methodBinding, enclosingMethodBinding); 1801 } 1802 1803 if (fNode instanceof ClassInstanceCreation) 1804 return enclosingMethodBinding == ((ClassInstanceCreation)fNode).resolveConstructorBinding(); 1805 1806 if (fNode instanceof ConstructorInvocation) 1807 return enclosingMethodBinding == ((ConstructorInvocation)fNode).resolveConstructorBinding(); 1808 1809 if (fNode instanceof SuperConstructorInvocation) { 1810 return false; } 1812 1813 if (fNode instanceof EnumConstantDeclaration) { 1814 return false; } 1816 1817 Assert.isTrue(false); 1818 return false; 1819 } 1820 1821 1828 private boolean isSameMethod(IMethodBinding m1, IMethodBinding m2) { 1829 if (m1.isConstructor()) { 1830 if (! m2.isConstructor()) 1831 return false; 1832 } else { 1833 if (! m1.getName().equals(m2.getName())) 1834 return false; 1835 } 1836 1837 ITypeBinding[] m1Parameters= m1.getParameterTypes(); 1838 ITypeBinding[] m2Parameters= m2.getParameterTypes(); 1839 if (m1Parameters.length != m2Parameters.length) 1840 return false; 1841 for (int i= 0; i < m1Parameters.length; i++) { 1842 if (m1Parameters[i].getErasure() != m2Parameters[i].getErasure()) 1843 return false; 1844 } 1845 return true; 1846 } 1847 1848 } 1849 1850 class DeclarationUpdate extends OccurrenceUpdate { 1851 private MethodDeclaration fMethDecl; 1852 1853 protected DeclarationUpdate(MethodDeclaration decl, CompilationUnitRewrite cuRewrite, RefactoringStatus result) { 1854 super(cuRewrite, cuRewrite.createGroupDescription(RefactoringCoreMessages.ChangeSignatureRefactoring_change_signature), result); 1855 fMethDecl= decl; 1856 } 1857 1858 protected void registerImportRemoveNode(ASTNode node) { 1860 if (!fDelegateUpdating) 1861 super.registerImportRemoveNode(node); 1862 } 1863 1864 public void updateNode() throws CoreException { 1865 changeParamguments(); 1866 1867 if (canChangeNameAndReturnType()) { 1868 changeMethodName(); 1869 changeReturnType(); 1870 } 1871 1872 if (needsVisibilityUpdate()) 1873 changeVisibility(); 1874 reshuffleElements(); 1875 changeExceptions(); 1876 1877 changeJavadocTags(); 1878 1879 if (fBodyUpdater == null || fBodyUpdater.needsParameterUsedCheck()) 1880 checkIfDeletedParametersUsed(); 1881 1882 if (fBodyUpdater != null) 1883 fBodyUpdater.updateBody(fMethDecl, fCuRewrite, fResult); 1884 1885 if (fDelegateUpdating) 1886 addDelegate(); 1887 } 1888 1889 private void addDelegate() throws JavaModelException { 1890 1891 DelegateMethodCreator creator= new DelegateMethodCreator(); 1892 creator.setDeclaration(fMethDecl); 1893 creator.setDeclareDeprecated(fDelegateDeprecation); 1894 creator.setSourceRewrite(fCuRewrite); 1895 creator.prepareDelegate(); 1896 1897 1904 final ASTNode delegateInvocation= creator.getDelegateInvocation(); 1905 if (delegateInvocation != null) 1906 new ReferenceUpdate(delegateInvocation, creator.getDelegateRewrite(), fResult).updateNode(); 1909 new DocReferenceUpdate(creator.getJavadocReference(), creator.getDelegateRewrite(), fResult).updateNode(); 1910 1911 creator.createEdit(); 1912 } 1913 1914 1915 protected ListRewrite getParamgumentsRewrite() { 1916 return getASTRewrite().getListRewrite(fMethDecl, MethodDeclaration.PARAMETERS_PROPERTY); 1917 } 1918 1919 protected void changeParamgumentName(ParameterInfo info) { 1920 SingleVariableDeclaration param= (SingleVariableDeclaration) fMethDecl.parameters().get(info.getOldIndex()); 1921 if (! info.getOldName().equals(param.getName().getIdentifier())) 1922 return; 1924 String msg= RefactoringCoreMessages.ChangeSignatureRefactoring_update_parameter_references; 1925 TextEditGroup description= fCuRewrite.createGroupDescription(msg); 1926 TempOccurrenceAnalyzer analyzer= new TempOccurrenceAnalyzer(param, false); 1927 analyzer.perform(); 1928 SimpleName[] paramOccurrences= analyzer.getReferenceAndDeclarationNodes(); for (int j= 0; j < paramOccurrences.length; j++) { 1930 SimpleName occurence= paramOccurrences[j]; 1931 getASTRewrite().set(occurence, SimpleName.IDENTIFIER_PROPERTY, info.getNewName(), description); 1932 } 1933 } 1934 1935 protected void changeParamgumentType(ParameterInfo info) { 1936 SingleVariableDeclaration oldParam= (SingleVariableDeclaration) fMethDecl.parameters().get(info.getOldIndex()); 1937 getASTRewrite().set(oldParam, SingleVariableDeclaration.VARARGS_PROPERTY, Boolean.valueOf(info.isNewVarargs()), fDescription); 1938 replaceTypeNode(oldParam.getType(), ParameterInfo.stripEllipsis(info.getNewTypeName()), info.getNewTypeBinding()); 1939 removeExtraDimensions(oldParam); 1940 } 1941 1942 private void removeExtraDimensions(SingleVariableDeclaration oldParam) { 1943 if (oldParam.getExtraDimensions() != 0) { 1944 getASTRewrite().set(oldParam, SingleVariableDeclaration.EXTRA_DIMENSIONS_PROPERTY, new Integer (0), fDescription); 1945 } 1946 } 1947 1948 private void changeReturnType() throws JavaModelException { 1949 if (isReturnTypeSameAsInitial()) 1950 return; 1951 replaceTypeNode(fMethDecl.getReturnType2(), fReturnTypeInfo.getNewTypeName(), fReturnTypeInfo.getNewTypeBinding()); 1952 removeExtraDimensions(fMethDecl); 1953 } 1956 1957 private void removeExtraDimensions(MethodDeclaration methDecl) { 1958 if (methDecl.getExtraDimensions() != 0) 1959 getASTRewrite().set(methDecl, MethodDeclaration.EXTRA_DIMENSIONS_PROPERTY, new Integer (0), fDescription); 1960 } 1961 1962 private boolean needsVisibilityUpdate() throws JavaModelException { 1963 if (isVisibilitySameAsInitial()) 1964 return false; 1965 if (isIncreasingVisibility()) 1966 return JdtFlags.isHigherVisibility(fVisibility, JdtFlags.getVisibilityCode(fMethDecl)); 1967 else 1968 return JdtFlags.isHigherVisibility(JdtFlags.getVisibilityCode(fMethDecl), fVisibility); 1969 } 1970 1971 private boolean isIncreasingVisibility() throws JavaModelException{ 1972 return JdtFlags.isHigherVisibility(fVisibility, JdtFlags.getVisibilityCode(fMethod)); 1973 } 1974 1975 private void changeVisibility() { 1976 ModifierRewrite.create(getASTRewrite(), fMethDecl).setVisibility(fVisibility, fDescription); 1977 } 1978 1979 private void changeExceptions() { 1980 for (Iterator iter= fExceptionInfos.iterator(); iter.hasNext();) { 1981 ExceptionInfo info= (ExceptionInfo) iter.next(); 1982 if (info.isOld()) 1983 continue; 1984 if (info.isDeleted()) 1985 removeExceptionFromNodeList(info, fMethDecl.thrownExceptions()); 1986 else 1987 addExceptionToNodeList(info, getASTRewrite().getListRewrite(fMethDecl, MethodDeclaration.THROWN_EXCEPTIONS_PROPERTY)); 1988 } 1989 } 1990 1991 private void removeExceptionFromNodeList(ExceptionInfo toRemove, List exceptionsNodeList) { 1992 ITypeBinding typeToRemove= toRemove.getTypeBinding(); 1993 for (Iterator iter= exceptionsNodeList.iterator(); iter.hasNext(); ) { 1994 Name currentName= (Name) iter.next(); 1995 ITypeBinding currentType= currentName.resolveTypeBinding(); 1996 2003 if (currentType == null) 2005 continue; if (Bindings.equals(currentType, typeToRemove) || toRemove.getType().getElementName().equals(currentType.getName())) { 2007 getASTRewrite().remove(currentName, fDescription); 2008 registerImportRemoveNode(currentName); 2009 } 2010 } 2011 } 2012 2013 private void addExceptionToNodeList(ExceptionInfo exceptionInfo, ListRewrite exceptionListRewrite) { 2014 String fullyQualified= JavaModelUtil.getFullyQualifiedName(exceptionInfo.getType()); 2015 for (Iterator iter= exceptionListRewrite.getOriginalList().iterator(); iter.hasNext(); ) { 2016 Name exName= (Name) iter.next(); 2017 ITypeBinding typeBinding= exName.resolveTypeBinding(); 2019 if (typeBinding == null) 2020 continue; if (typeBinding.getQualifiedName().equals(fullyQualified)) 2022 return; } 2024 String importedType= getImportRewrite().addImport(JavaModelUtil.getFullyQualifiedName(exceptionInfo.getType())); 2025 getImportRemover().registerAddedImport(importedType); 2026 ASTNode exNode= getASTRewrite().createStringPlaceholder(importedType, ASTNode.SIMPLE_NAME); 2027 exceptionListRewrite.insertLast(exNode, fDescription); 2028 } 2029 2030 private void changeJavadocTags() throws JavaModelException { 2031 Javadoc javadoc= fMethDecl.getJavadoc(); 2033 if (javadoc == null) 2034 return; 2035 2036 ITypeBinding typeBinding= Bindings.getBindingOfParentType(fMethDecl); 2037 if (typeBinding == null) 2038 return; 2039 IMethodBinding methodBinding= fMethDecl.resolveBinding(); 2040 if (methodBinding == null) 2041 return; 2042 2043 boolean isTopOfRipple= (Bindings.findOverriddenMethod(methodBinding, false) == null); 2044 2047 List tags= javadoc.tags(); ListRewrite tagsRewrite= getASTRewrite().getListRewrite(javadoc, Javadoc.TAGS_PROPERTY); 2049 2050 if (! isReturnTypeSameAsInitial()) { 2051 if (PrimitiveType.VOID.toString().equals(fReturnTypeInfo.getNewTypeName())) { 2052 for (int i = 0; i < tags.size(); i++) { 2053 TagElement tag= (TagElement) tags.get(i); 2054 if (TagElement.TAG_RETURN.equals(tag.getTagName())) { 2055 getASTRewrite().remove(tag, fDescription); 2056 registerImportRemoveNode(tag); 2057 } 2058 } 2059 } else if (isTopOfRipple && Signature.SIG_VOID.equals(fMethod.getReturnType())){ 2060 TagElement returnNode= createReturnTag(); 2061 TagElement previousTag= findTagElementToInsertAfter(tags, TagElement.TAG_RETURN); 2062 insertTag(returnNode, previousTag, tagsRewrite); 2063 tags= tagsRewrite.getRewrittenList(); 2064 } 2065 } 2066 2067 if (! (areNamesSameAsInitial() && isOrderSameAsInitial())) { 2068 ArrayList paramTags= new ArrayList (); for (Iterator iter = tags.iterator(); iter.hasNext(); ) { 2071 TagElement tag = (TagElement) iter.next(); 2072 String tagName= tag.getTagName(); 2073 List fragments= tag.fragments(); 2074 if (! (TagElement.TAG_PARAM.equals(tagName) && fragments.size() > 0 && fragments.get(0) instanceof SimpleName)) 2075 continue; 2076 SimpleName simpleName= (SimpleName) fragments.get(0); 2077 String identifier= simpleName.getIdentifier(); 2078 boolean removed= false; 2079 for (int i= 0; i < fParameterInfos.size(); i++) { 2080 ParameterInfo info= (ParameterInfo) fParameterInfos.get(i); 2081 if (identifier.equals(info.getOldName())) { 2082 if (info.isDeleted()) { 2083 getASTRewrite().remove(tag, fDescription); 2084 registerImportRemoveNode(tag); 2085 removed= true; 2086 } else if (info.isRenamed()) { 2087 SimpleName newName= simpleName.getAST().newSimpleName(info.getNewName()); 2088 getASTRewrite().replace(simpleName, newName, fDescription); 2089 registerImportRemoveNode(tag); 2090 } 2091 break; 2092 } 2093 } 2094 if (! removed) 2095 paramTags.add(tag); 2096 } 2097 tags= tagsRewrite.getRewrittenList(); 2098 2099 if (! isOrderSameAsInitial()) { 2100 TagElement previousTag= findTagElementToInsertAfter(tags, TagElement.TAG_PARAM); 2102 boolean first= true; for (Iterator infoIter= fParameterInfos.iterator(); infoIter.hasNext();) { 2105 ParameterInfo info= (ParameterInfo) infoIter.next(); 2106 String oldName= info.getOldName(); 2107 String newName= info.getNewName(); 2108 if (info.isAdded()) { 2109 first= false; 2110 if (! isTopOfRipple) 2111 continue; 2112 TagElement paramNode= JavadocUtil.createParamTag(newName, fCuRewrite.getRoot().getAST(), fCuRewrite.getCu().getJavaProject()); 2113 insertTag(paramNode, previousTag, tagsRewrite); 2114 previousTag= paramNode; 2115 } else { 2116 for (Iterator tagIter= paramTags.iterator(); tagIter.hasNext();) { 2117 TagElement tag= (TagElement) tagIter.next(); 2118 SimpleName tagName= (SimpleName) tag.fragments().get(0); 2119 if (oldName.equals(tagName.getIdentifier())) { 2120 tagIter.remove(); 2121 if (first) { 2122 previousTag= tag; 2123 } else { 2124 TagElement movedTag= (TagElement) getASTRewrite().createMoveTarget(tag); 2125 getASTRewrite().remove(tag, fDescription); 2126 insertTag(movedTag, previousTag, tagsRewrite); 2127 previousTag= movedTag; 2128 } 2129 } 2130 first= false; 2131 } 2132 } 2133 } 2134 for (Iterator iter= paramTags.iterator(); iter.hasNext();) { 2136 TagElement tag= (TagElement) iter.next(); 2137 TagElement movedTag= (TagElement) getASTRewrite().createMoveTarget(tag); 2138 getASTRewrite().remove(tag, fDescription); 2139 insertTag(movedTag, previousTag, tagsRewrite); 2140 previousTag= movedTag; 2141 } 2142 } 2143 tags= tagsRewrite.getRewrittenList(); 2144 } 2145 2146 if (! areExceptionsSameAsInitial()) { 2147 ArrayList exceptionTags= new ArrayList (); for (int i= 0; i < tags.size(); i++) { 2150 TagElement tag= (TagElement) tags.get(i); 2151 if (! TagElement.TAG_THROWS.equals(tag.getTagName()) && ! TagElement.TAG_EXCEPTION.equals(tag.getTagName())) 2152 continue; 2153 if (! (tag.fragments().size() > 0 && tag.fragments().get(0) instanceof Name)) 2154 continue; 2155 boolean tagDeleted= false; 2156 Name name= (Name) tag.fragments().get(0); 2157 for (int j= 0; j < fExceptionInfos.size(); j++) { 2158 ExceptionInfo info= (ExceptionInfo) fExceptionInfos.get(j); 2159 if (info.isDeleted()) { 2160 boolean remove= false; 2161 final ITypeBinding nameBinding= name.resolveTypeBinding(); 2162 if (nameBinding != null) { 2163 final ITypeBinding infoBinding= info.getTypeBinding(); 2164 if (infoBinding != null && Bindings.equals(infoBinding, nameBinding)) 2165 remove= true; 2166 else if (info.getType().getElementName().equals(nameBinding.getName())) 2167 remove= true; 2168 if (remove) { 2169 getASTRewrite().remove(tag, fDescription); 2170 registerImportRemoveNode(tag); 2171 tagDeleted= true; 2172 break; 2173 } 2174 } 2175 } 2176 } 2177 if (! tagDeleted) 2178 exceptionTags.add(tag); 2179 } 2180 tags= tagsRewrite.getRewrittenList(); 2182 TagElement previousTag= findTagElementToInsertAfter(tags, TagElement.TAG_THROWS); 2183 for (Iterator infoIter= fExceptionInfos.iterator(); infoIter.hasNext();) { 2184 ExceptionInfo info= (ExceptionInfo) infoIter.next(); 2185 if (info.isAdded()) { 2186 if (!isTopOfRipple) 2187 continue; 2188 TagElement excptNode= createExceptionTag(info.getType().getElementName()); 2189 insertTag(excptNode, previousTag, tagsRewrite); 2190 previousTag= excptNode; 2191 } else { 2192 for (Iterator tagIter= exceptionTags.iterator(); tagIter.hasNext();) { 2193 TagElement tag= (TagElement) tagIter.next(); 2194 Name tagName= (Name) tag.fragments().get(0); 2195 final ITypeBinding nameBinding= tagName.resolveTypeBinding(); 2196 if (nameBinding != null) { 2197 boolean process= false; 2198 final ITypeBinding infoBinding= info.getTypeBinding(); 2199 if (infoBinding != null && Bindings.equals(infoBinding, nameBinding)) 2200 process= true; 2201 else if (info.getType().getElementName().equals(nameBinding.getName())) 2202 process= true; 2203 if (process) { 2204 tagIter.remove(); 2205 TagElement movedTag= (TagElement) getASTRewrite().createMoveTarget(tag); 2206 getASTRewrite().remove(tag, fDescription); 2207 insertTag(movedTag, previousTag, tagsRewrite); 2208 previousTag= movedTag; 2209 } 2210 } 2211 } 2212 } 2213 } 2214 for (Iterator iter= exceptionTags.iterator(); iter.hasNext();) { 2216 TagElement tag= (TagElement) iter.next(); 2217 TagElement movedTag= (TagElement) getASTRewrite().createMoveTarget(tag); 2218 getASTRewrite().remove(tag, fDescription); 2219 insertTag(movedTag, previousTag, tagsRewrite); 2220 previousTag= movedTag; 2221 } 2222 } 2223 } 2224 2225 private TagElement createReturnTag() { 2226 TagElement returnNode= getASTRewrite().getAST().newTagElement(); 2227 returnNode.setTagName(TagElement.TAG_RETURN); 2228 2229 TextElement textElement= getASTRewrite().getAST().newTextElement(); 2230 String text= StubUtility.getTodoTaskTag(fCuRewrite.getCu().getJavaProject()); 2231 if (text != null) 2232 textElement.setText(text); returnNode.fragments().add(textElement); 2234 2235 return returnNode; 2236 } 2237 2238 private TagElement createExceptionTag(String simpleName) { 2239 TagElement excptNode= getASTRewrite().getAST().newTagElement(); 2240 excptNode.setTagName(TagElement.TAG_THROWS); 2241 2242 SimpleName nameNode= getASTRewrite().getAST().newSimpleName(simpleName); 2243 excptNode.fragments().add(nameNode); 2244 2245 TextElement textElement= getASTRewrite().getAST().newTextElement(); 2246 String text= StubUtility.getTodoTaskTag(fCuRewrite.getCu().getJavaProject()); 2247 if (text != null) 2248 textElement.setText(text); excptNode.fragments().add(textElement); 2250 2251 return excptNode; 2252 } 2253 2254 private void insertTag(TagElement tag, TagElement previousTag, ListRewrite tagsRewrite) { 2255 if (previousTag == null) 2256 tagsRewrite.insertFirst(tag, fDescription); 2257 else 2258 tagsRewrite.insertAfter(tag, previousTag, fDescription); 2259 } 2260 2261 2267 private TagElement findTagElementToInsertAfter(List tags, String tagName) { 2268 List tagOrder= Arrays.asList(new String [] { 2269 TagElement.TAG_AUTHOR, 2270 TagElement.TAG_VERSION, 2271 TagElement.TAG_PARAM, 2272 TagElement.TAG_RETURN, 2273 TagElement.TAG_THROWS, 2274 TagElement.TAG_EXCEPTION, 2275 TagElement.TAG_SEE, 2276 TagElement.TAG_SINCE, 2277 TagElement.TAG_SERIAL, 2278 TagElement.TAG_SERIALFIELD, 2279 TagElement.TAG_SERIALDATA, 2280 TagElement.TAG_DEPRECATED, 2281 TagElement.TAG_VALUE 2282 }); 2283 int goalOrdinal= tagOrder.indexOf(tagName); 2284 if (goalOrdinal == -1) return (tags.size() == 0) ? null : (TagElement) tags.get(tags.size()); 2286 for (int i= 0; i < tags.size(); i++) { 2287 int tagOrdinal= tagOrder.indexOf(((TagElement) tags.get(i)).getTagName()); 2288 if (tagOrdinal >= goalOrdinal) 2289 return (i == 0) ? null : (TagElement) tags.get(i-1); 2290 } 2291 return (tags.size() == 0) ? null : (TagElement) tags.get(tags.size()-1); 2292 } 2293 2294 private void checkIfDeletedParametersUsed() { 2296 for (Iterator iter= getDeletedInfos().iterator(); iter.hasNext();) { 2297 ParameterInfo info= (ParameterInfo) iter.next(); 2298 SingleVariableDeclaration paramDecl= (SingleVariableDeclaration) fMethDecl.parameters().get(info.getOldIndex()); 2299 TempOccurrenceAnalyzer analyzer= new TempOccurrenceAnalyzer(paramDecl, false); 2300 analyzer.perform(); 2301 SimpleName[] paramRefs= analyzer.getReferenceNodes(); 2302 2303 if (paramRefs.length > 0){ 2304 RefactoringStatusContext context= JavaStatusContext.create(fCuRewrite.getCu(), paramRefs[0]); 2305 String typeName= getFullTypeName(fMethDecl); 2306 Object [] keys= new String []{paramDecl.getName().getIdentifier(), 2307 fMethDecl.getName().getIdentifier(), 2308 typeName}; 2309 String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_parameter_used, keys); 2310 fResult.addError(msg, context); 2311 } 2312 } 2313 } 2314 2315 private String getFullTypeName(MethodDeclaration decl) { 2316 ASTNode node= decl; 2317 while (true) { 2318 node= node.getParent(); 2319 if (node instanceof AbstractTypeDeclaration) { 2320 return ((AbstractTypeDeclaration) node).getName().getIdentifier(); 2321 } else if (node instanceof ClassInstanceCreation) { 2322 ClassInstanceCreation cic= (ClassInstanceCreation) node; 2323 return Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_anonymous_subclass, new String []{ASTNodes.asString(cic.getType())}); 2324 } else if (node instanceof EnumConstantDeclaration) { 2325 EnumDeclaration ed= (EnumDeclaration) node.getParent(); 2326 return Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_anonymous_subclass, new String []{ASTNodes.asString(ed.getName())}); 2327 } 2328 } 2329 } 2330 2331 protected ASTNode createNewParamgument(ParameterInfo info, List parameterInfos, List nodes) { 2332 return createNewSingleVariableDeclaration(info); 2333 } 2334 2335 private SingleVariableDeclaration createNewSingleVariableDeclaration(ParameterInfo info) { 2336 SingleVariableDeclaration newP= getASTRewrite().getAST().newSingleVariableDeclaration(); 2337 newP.setName(getASTRewrite().getAST().newSimpleName(info.getNewName())); 2338 newP.setType(createNewTypeNode(ParameterInfo.stripEllipsis(info.getNewTypeName()), info.getNewTypeBinding())); 2339 newP.setVarargs(info.isNewVarargs()); 2340 return newP; 2341 } 2342 2343 protected SimpleName getMethodNameNode() { 2344 return fMethDecl.getName(); 2345 } 2346 2347 } 2348 2349 class DocReferenceUpdate extends OccurrenceUpdate { 2350 2351 private ASTNode fNode; 2352 2353 protected DocReferenceUpdate(ASTNode node, CompilationUnitRewrite cuRewrite, RefactoringStatus result) { 2354 super(cuRewrite, cuRewrite.createGroupDescription(RefactoringCoreMessages.ChangeSignatureRefactoring_update_javadoc_reference), result); 2355 fNode= node; 2356 } 2357 2358 public void updateNode() { 2359 if (fNode instanceof MethodRef) { 2360 changeParamguments(); 2361 reshuffleElements(); 2362 } 2363 if (canChangeNameAndReturnType()) 2364 changeMethodName(); 2365 } 2366 2367 protected ASTNode createNewParamgument(ParameterInfo info, List parameterInfos, List nodes) { 2368 return createNewMethodRefParameter(info); 2369 } 2370 2371 private MethodRefParameter createNewMethodRefParameter(ParameterInfo info) { 2372 MethodRefParameter newP= getASTRewrite().getAST().newMethodRefParameter(); 2373 2374 List parameters= getParamgumentsRewrite().getOriginalList(); 2376 if (parameters.size() > 0) 2377 if (((MethodRefParameter) parameters.get(0)).getName() != null) 2378 newP.setName(getASTRewrite().getAST().newSimpleName(info.getNewName())); 2379 2380 newP.setType(createNewDocRefType(info)); 2381 newP.setVarargs(info.isNewVarargs()); 2382 return newP; 2383 } 2384 2385 private Type createNewDocRefType(ParameterInfo info) { 2386 String newTypeName= ParameterInfo.stripEllipsis(info.getNewTypeName()); 2387 ITypeBinding newTypeBinding= info.getNewTypeBinding(); 2388 if (newTypeBinding != null) 2389 newTypeBinding= newTypeBinding.getErasure(); return createNewTypeNode(newTypeName, newTypeBinding); 2391 } 2392 2393 protected SimpleName getMethodNameNode() { 2394 if (fNode instanceof MemberRef) 2395 return ((MemberRef) fNode).getName(); 2396 2397 if (fNode instanceof MethodRef) 2398 return ((MethodRef) fNode).getName(); 2399 2400 return null; 2401 } 2402 2403 2404 protected ListRewrite getParamgumentsRewrite() { 2405 return getASTRewrite().getListRewrite(fNode, MethodRef.PARAMETERS_PROPERTY); 2406 } 2407 2408 protected void changeParamgumentName(ParameterInfo info) { 2409 if (! (fNode instanceof MethodRef)) 2410 return; 2411 2412 MethodRefParameter oldParam= (MethodRefParameter) ((MethodRef) fNode).parameters().get(info.getOldIndex()); 2413 SimpleName oldParamName= oldParam.getName(); 2414 if (oldParamName != null) 2415 getASTRewrite().set(oldParamName, SimpleName.IDENTIFIER_PROPERTY, info.getNewName(), fDescription); 2416 } 2417 2418 protected void changeParamgumentType(ParameterInfo info) { 2419 if (! (fNode instanceof MethodRef)) 2420 return; 2421 2422 MethodRefParameter oldParam= (MethodRefParameter) ((MethodRef) fNode).parameters().get(info.getOldIndex()); 2423 Type oldTypeNode= oldParam.getType(); 2424 Type newTypeNode= createNewDocRefType(info); 2425 if (info.isNewVarargs()) { 2426 if (info.isOldVarargs() && ! oldParam.isVarargs()) { 2427 newTypeNode= getASTRewrite().getAST().newArrayType(newTypeNode); 2429 } else { 2430 getASTRewrite().set(oldParam, MethodRefParameter.VARARGS_PROPERTY, Boolean.TRUE, fDescription); 2431 } 2432 } else { 2433 if (oldParam.isVarargs()) { 2434 getASTRewrite().set(oldParam, MethodRefParameter.VARARGS_PROPERTY, Boolean.FALSE, fDescription); 2435 } 2436 } 2437 2438 getASTRewrite().replace(oldTypeNode, newTypeNode, fDescription); 2439 registerImportRemoveNode(oldTypeNode); 2440 } 2441 } 2442 2443 class StaticImportUpdate extends OccurrenceUpdate { 2444 2445 private final ImportDeclaration fImportDecl; 2446 2447 public StaticImportUpdate(ImportDeclaration importDecl, CompilationUnitRewrite cuRewrite, RefactoringStatus result) { 2448 super(cuRewrite, null, result); 2449 fImportDecl= importDecl; 2450 } 2451 2452 public void updateNode() throws JavaModelException { 2453 ImportRewrite importRewrite= fCuRewrite.getImportRewrite(); 2454 QualifiedName name= (QualifiedName) fImportDecl.getName(); 2455 importRewrite.addStaticImport(name.getQualifier().getFullyQualifiedName(), fMethodName, false); 2457 } 2458 2459 protected ListRewrite getParamgumentsRewrite() { 2460 return null; 2461 } 2462 2463 protected ASTNode createNewParamgument(ParameterInfo info, List parameterInfos, List nodes) { 2464 return null; 2465 } 2466 2467 protected SimpleName getMethodNameNode() { 2468 return null; 2469 } 2470 } 2471 2472 class NullOccurrenceUpdate extends OccurrenceUpdate { 2473 private ASTNode fNode; 2474 protected NullOccurrenceUpdate(ASTNode node, CompilationUnitRewrite cuRewrite, RefactoringStatus result) { 2475 super(cuRewrite, null, result); 2476 fNode= node; 2477 } 2478 public void updateNode() throws JavaModelException { 2479 int start= fNode.getStartPosition(); 2480 int length= fNode.getLength(); 2481 String msg= "Cannot update found node: nodeType=" + fNode.getNodeType() + "; " + fNode.toString() + "[" + start + ", " + length + "] in " + fCuRewrite.getCu(); JavaPlugin.log(new Exception (msg + ":\n" + fCuRewrite.getCu().getSource().substring(start, start + length))); fResult.addError(msg, JavaStatusContext.create(fCuRewrite.getCu(), fNode)); 2485 } 2486 protected ListRewrite getParamgumentsRewrite() { 2487 return null; 2488 } 2489 protected ASTNode createNewParamgument(ParameterInfo info, List parameterInfos, List nodes) { 2490 return null; 2491 } 2492 protected SimpleName getMethodNameNode() { 2493 return null; 2494 } 2495 } 2496 2497 public RefactoringStatus initialize(final RefactoringArguments arguments) { 2498 if (arguments instanceof JavaRefactoringArguments) { 2499 final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments; 2500 final String handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT); 2501 if (handle != null) { 2502 final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false); 2503 if (element == null || !element.exists() || element.getElementType() != IJavaElement.METHOD) 2504 return createInputFatalStatus(element, IJavaRefactorings.CHANGE_METHOD_SIGNATURE); 2505 else { 2506 fMethod= (IMethod) element; 2507 fMethodName= fMethod.getElementName(); 2508 try { 2509 fVisibility= JdtFlags.getVisibilityCode(fMethod); 2510 fReturnTypeInfo= new ReturnTypeInfo(Signature.toString(Signature.getReturnType(fMethod.getSignature()))); 2511 } catch (JavaModelException exception) { 2512 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, ATTRIBUTE_VISIBILITY)); 2513 } 2514 } 2515 } else 2516 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT)); 2517 final String name= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_NAME); 2518 if (name != null) { 2519 fMethodName= name; 2520 final RefactoringStatus status= Checks.checkMethodName(fMethodName); 2521 if (status.hasError()) 2522 return status; 2523 } else 2524 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_NAME)); 2525 final String type= extended.getAttribute(ATTRIBUTE_RETURN); 2526 if (type != null && !"".equals(type)) fReturnTypeInfo= new ReturnTypeInfo(type); 2528 final String visibility= extended.getAttribute(ATTRIBUTE_VISIBILITY); 2529 if (visibility != null && !"".equals(visibility)) { int flag= 0; 2531 try { 2532 flag= Integer.parseInt(visibility); 2533 } catch (NumberFormatException exception) { 2534 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_VISIBILITY)); 2535 } 2536 fVisibility= flag; 2537 } 2538 int count= 1; 2539 String attribute= ATTRIBUTE_PARAMETER + count; 2540 String value= null; 2541 fParameterInfos= new ArrayList (3); 2542 while ((value= extended.getAttribute(attribute)) != null) { 2543 StringTokenizer tokenizer= new StringTokenizer (value); 2544 if (tokenizer.countTokens() < 6) 2545 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, ATTRIBUTE_PARAMETER)); 2546 String oldTypeName= tokenizer.nextToken(); 2547 String oldName= tokenizer.nextToken(); 2548 String oldIndex= tokenizer.nextToken(); 2549 String newTypeName= tokenizer.nextToken(); 2550 String newName= tokenizer.nextToken(); 2551 String deleted= tokenizer.nextToken(); 2552 ParameterInfo info= null; 2553 try { 2554 info= new ParameterInfo(oldTypeName, oldName, Integer.valueOf(oldIndex).intValue()); 2555 info.setNewTypeName(newTypeName); 2556 info.setNewName(newName); 2557 if (Boolean.valueOf(deleted).booleanValue()) 2558 info.markAsDeleted(); 2559 fParameterInfos.add(info); 2560 } catch (NumberFormatException exception) { 2561 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, ATTRIBUTE_PARAMETER)); 2562 } 2563 final String result= extended.getAttribute(ATTRIBUTE_DEFAULT + count); 2564 if (result != null && !"".equals(result)) info.setDefaultValue(result); 2566 count++; 2567 attribute= ATTRIBUTE_PARAMETER + count; 2568 } 2569 count= 1; 2570 fExceptionInfos= new ArrayList (2); 2571 attribute= JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + count; 2572 while ((value= extended.getAttribute(attribute)) != null) { 2573 ExceptionInfo info= null; 2574 final String kind= extended.getAttribute(ATTRIBUTE_KIND + count); 2575 if (kind != null) { 2576 final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), value, false); 2577 if (element == null || !element.exists()) 2578 return createInputFatalStatus(element, IJavaRefactorings.CHANGE_METHOD_SIGNATURE); 2579 else { 2580 try { 2581 info= new ExceptionInfo((IType) element, Integer.valueOf(kind).intValue(), null); 2582 } catch (NumberFormatException exception) { 2583 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, ATTRIBUTE_KIND)); 2584 } 2585 } 2586 } else 2587 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, ATTRIBUTE_KIND)); 2588 fExceptionInfos.add(info); 2589 count++; 2590 attribute= JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + count; 2591 } 2592 final String deprecate= extended.getAttribute(ATTRIBUTE_DEPRECATE); 2593 if (deprecate != null) { 2594 fDelegateDeprecation= Boolean.valueOf(deprecate).booleanValue(); 2595 } else 2596 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_DEPRECATE)); 2597 final String delegate= extended.getAttribute(ATTRIBUTE_DELEGATE); 2598 if (delegate != null) { 2599 fDelegateUpdating= Boolean.valueOf(delegate).booleanValue(); 2600 } else 2601 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_DELEGATE)); 2602 } else 2603 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments); 2604 return new RefactoringStatus(); 2605 } 2606 2607 2620 protected ASTNode moveNode(ASTNode oldNode, ASTRewrite rewrite) { 2621 ASTNode movedNode; 2622 if (ASTNodes.isExistingNode(oldNode)) 2623 movedNode= rewrite.createMoveTarget(oldNode); else 2625 movedNode= ASTNode.copySubtree(rewrite.getAST(), oldNode); 2626 return movedNode; 2627 } 2628 2629 public String getDelegateUpdatingTitle(boolean plural) { 2630 if (plural) 2631 return RefactoringCoreMessages.DelegateCreator_keep_original_changed_plural; 2632 else 2633 return RefactoringCoreMessages.DelegateCreator_keep_original_changed_singular; 2634 } 2635 2636 public IDefaultValueAdvisor getDefaultValueAdvisor() { 2637 return fDefaultValueAdvisor; 2638 } 2639 2640 public void setDefaultValueAdvisor(IDefaultValueAdvisor defaultValueAdvisor) { 2641 fDefaultValueAdvisor= defaultValueAdvisor; 2642 } 2643} 2644 | Popular Tags |