| 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 |