1 11 package org.eclipse.jdt.internal.corext.refactoring.rename; 12 13 import org.eclipse.core.runtime.Assert; 14 import org.eclipse.core.runtime.CoreException; 15 import org.eclipse.core.runtime.IProgressMonitor; 16 import org.eclipse.core.runtime.OperationCanceledException; 17 import org.eclipse.core.runtime.SubProgressMonitor; 18 19 import org.eclipse.core.resources.IFile; 20 21 import org.eclipse.ltk.core.refactoring.Change; 22 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; 23 import org.eclipse.ltk.core.refactoring.RefactoringStatus; 24 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; 25 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments; 26 import org.eclipse.ltk.core.refactoring.participants.RenameArguments; 27 28 import org.eclipse.jdt.core.ICompilationUnit; 29 import org.eclipse.jdt.core.IJavaElement; 30 import org.eclipse.jdt.core.IJavaProject; 31 import org.eclipse.jdt.core.IMember; 32 import org.eclipse.jdt.core.IMethod; 33 import org.eclipse.jdt.core.ISourceRange; 34 import org.eclipse.jdt.core.IType; 35 import org.eclipse.jdt.core.ITypeParameter; 36 import org.eclipse.jdt.core.dom.ASTNode; 37 import org.eclipse.jdt.core.dom.ASTVisitor; 38 import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration; 39 import org.eclipse.jdt.core.dom.CompilationUnit; 40 import org.eclipse.jdt.core.dom.EnumDeclaration; 41 import org.eclipse.jdt.core.dom.IBinding; 42 import org.eclipse.jdt.core.dom.ITypeBinding; 43 import org.eclipse.jdt.core.dom.SimpleName; 44 import org.eclipse.jdt.core.dom.TypeDeclaration; 45 import org.eclipse.jdt.core.refactoring.IJavaRefactorings; 46 import org.eclipse.jdt.core.refactoring.descriptors.RenameJavaElementDescriptor; 47 48 import org.eclipse.jdt.internal.corext.SourceRange; 49 import org.eclipse.jdt.internal.corext.dom.Bindings; 50 import org.eclipse.jdt.internal.corext.dom.NodeFinder; 51 import org.eclipse.jdt.internal.corext.refactoring.Checks; 52 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor; 53 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment; 54 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments; 55 import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester; 56 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; 57 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext; 58 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange; 59 import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring; 60 import org.eclipse.jdt.internal.corext.refactoring.participants.JavaProcessors; 61 import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil; 62 import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite; 63 import org.eclipse.jdt.internal.corext.refactoring.tagging.IReferenceUpdating; 64 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser; 65 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil; 66 import org.eclipse.jdt.internal.corext.util.Messages; 67 68 import org.eclipse.jdt.ui.JavaElementLabels; 69 70 import org.eclipse.jdt.internal.ui.JavaPlugin; 71 import org.eclipse.jdt.internal.ui.refactoring.RefactoringSaveHelper; 72 73 76 public final class RenameTypeParameterProcessor extends JavaRenameProcessor implements IReferenceUpdating { 77 78 81 public final class RenameTypeParameterVisitor extends ASTVisitor { 82 83 84 private final IBinding fBinding; 85 86 87 private final SimpleName fName; 88 89 90 private final CompilationUnitRewrite fRewrite; 91 92 93 private final RefactoringStatus fStatus; 94 95 105 public RenameTypeParameterVisitor(final CompilationUnitRewrite rewrite, final ISourceRange range, final RefactoringStatus status) { 106 super(true); 107 Assert.isNotNull(rewrite); 108 Assert.isNotNull(range); 109 Assert.isNotNull(status); 110 fRewrite= rewrite; 111 fName= (SimpleName) NodeFinder.perform(rewrite.getRoot(), range); 112 fBinding= fName.resolveBinding(); 113 fStatus= status; 114 } 115 116 123 public final Change getResult() throws CoreException { 124 return fRewrite.createChange(); 125 } 126 127 public final boolean visit(final AnnotationTypeDeclaration node) { 128 final String name= node.getName().getIdentifier(); 129 if (name.equals(getNewElementName())) { 130 fStatus.addError(Messages.format(RefactoringCoreMessages.RenameTypeParameterRefactoring_type_parameter_inner_class_clash, new String [] { name}), JavaStatusContext.create(fTypeParameter.getDeclaringMember().getCompilationUnit(), new SourceRange(node))); 131 return false; 132 } 133 return true; 134 } 135 136 public final boolean visit(final EnumDeclaration node) { 137 final String name= node.getName().getIdentifier(); 138 if (name.equals(getNewElementName())) { 139 fStatus.addError(Messages.format(RefactoringCoreMessages.RenameTypeParameterRefactoring_type_parameter_inner_class_clash, new String [] { name}), JavaStatusContext.create(fTypeParameter.getDeclaringMember().getCompilationUnit(), new SourceRange(node))); 140 return false; 141 } 142 return true; 143 } 144 145 public final boolean visit(final SimpleName node) { 146 final ITypeBinding binding= node.resolveTypeBinding(); 147 if (binding != null && binding.isTypeVariable() && Bindings.equals(binding, fBinding) && node.getIdentifier().equals(fName.getIdentifier())) { 148 if (node != fName) { 149 if (fUpdateReferences) 150 fRewrite.getASTRewrite().set(node, SimpleName.IDENTIFIER_PROPERTY, getNewElementName(), fRewrite.createGroupDescription(RefactoringCoreMessages.RenameTypeParameterRefactoring_update_type_parameter_reference)); 151 } else 152 fRewrite.getASTRewrite().set(node, SimpleName.IDENTIFIER_PROPERTY, getNewElementName(), fRewrite.createGroupDescription(RefactoringCoreMessages.RenameTypeParameterRefactoring_update_type_parameter_declaration)); 153 } 154 return true; 155 } 156 157 public final boolean visit(final TypeDeclaration node) { 158 final String name= node.getName().getIdentifier(); 159 if (name.equals(getNewElementName())) { 160 fStatus.addError(Messages.format(RefactoringCoreMessages.RenameTypeParameterRefactoring_type_parameter_inner_class_clash, new String [] { name}), JavaStatusContext.create(fTypeParameter.getDeclaringMember().getCompilationUnit(), new SourceRange(node))); 161 return false; 162 } 163 return true; 164 } 165 } 166 167 private static final String ATTRIBUTE_PARAMETER= "parameter"; 169 170 public static final String IDENTIFIER= "org.eclipse.jdt.ui.renameTypeParameterProcessor"; 172 173 private Change fChange= null; 174 175 176 private ITypeParameter fTypeParameter; 177 178 179 private boolean fUpdateReferences= true; 180 181 187 public RenameTypeParameterProcessor(final ITypeParameter parameter) { 188 fTypeParameter= parameter; 189 if (parameter != null) 190 setNewElementName(parameter.getElementName()); 191 } 192 193 public final boolean canEnableUpdateReferences() { 194 return true; 195 } 196 197 protected RenameModifications computeRenameModifications() throws CoreException { 198 RenameModifications result= new RenameModifications(); 199 result.rename(fTypeParameter, new RenameArguments(getNewElementName(), getUpdateReferences())); 200 return result; 201 } 202 203 protected IFile[] getChangedFiles() throws CoreException { 204 return new IFile[] {ResourceUtil.getFile(fTypeParameter.getDeclaringMember().getCompilationUnit())}; 205 } 206 207 public int getSaveMode() { 208 return RefactoringSaveHelper.SAVE_NOTHING; 209 } 210 211 protected final RefactoringStatus doCheckFinalConditions(final IProgressMonitor monitor, final CheckConditionsContext context) throws CoreException, OperationCanceledException { 212 Assert.isNotNull(monitor); 213 Assert.isNotNull(context); 214 final RefactoringStatus status= new RefactoringStatus(); 215 try { 216 monitor.beginTask("", 5); monitor.setTaskName(RefactoringCoreMessages.RenameTypeParameterRefactoring_checking); 218 status.merge(Checks.checkIfCuBroken(fTypeParameter.getDeclaringMember())); 219 monitor.worked(1); 220 if (!status.hasFatalError()) { 221 status.merge(checkNewElementName(getNewElementName())); 222 monitor.worked(1); 223 monitor.setTaskName(RefactoringCoreMessages.RenameTypeParameterRefactoring_searching); 224 status.merge(createRenameChanges(new SubProgressMonitor(monitor, 2))); 225 monitor.setTaskName(RefactoringCoreMessages.RenameTypeParameterRefactoring_checking); 226 if (status.hasFatalError()) 227 return status; 228 monitor.worked(1); 229 } 230 } finally { 231 monitor.done(); 232 } 233 return status; 234 } 235 236 public final RefactoringStatus checkInitialConditions(final IProgressMonitor monitor) throws CoreException, OperationCanceledException { 237 Assert.isNotNull(monitor); 238 if (!fTypeParameter.exists()) 239 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.RenameTypeParameterRefactoring_deleted, fTypeParameter.getDeclaringMember().getCompilationUnit().getElementName())); 240 return Checks.checkIfCuBroken(fTypeParameter.getDeclaringMember()); 241 } 242 243 public final RefactoringStatus checkNewElementName(final String name) throws CoreException { 244 Assert.isNotNull(name); 245 final RefactoringStatus result= Checks.checkTypeParameterName(name); 246 if (Checks.startsWithLowerCase(name)) 247 result.addWarning(RefactoringCoreMessages.RenameTypeParameterRefactoring_should_start_lowercase); 248 if (Checks.isAlreadyNamed(fTypeParameter, name)) 249 result.addFatalError(RefactoringCoreMessages.RenameTypeParameterRefactoring_another_name); 250 251 final IMember member= fTypeParameter.getDeclaringMember(); 252 if (member instanceof IType) { 253 final IType type= (IType) member; 254 if (type.getTypeParameter(name).exists()) 255 result.addFatalError(RefactoringCoreMessages.RenameTypeParameterRefactoring_class_type_parameter_already_defined); 256 } else if (member instanceof IMethod) { 257 final IMethod method= (IMethod) member; 258 if (method.getTypeParameter(name).exists()) 259 result.addFatalError(RefactoringCoreMessages.RenameTypeParameterRefactoring_method_type_parameter_already_defined); 260 } else { 261 JavaPlugin.logErrorMessage("Unexpected sub-type of IMember: " + member.getClass().getName()); Assert.isTrue(false); 263 } 264 return result; 265 } 266 267 public final Change createChange(final IProgressMonitor monitor) throws CoreException, OperationCanceledException { 268 Assert.isNotNull(monitor); 269 try { 270 Change change= fChange; 271 if (change != null) { 272 String project= null; 273 IJavaProject javaProject= fTypeParameter.getJavaProject(); 274 if (javaProject != null) 275 project= javaProject.getElementName(); 276 final String description= Messages.format(RefactoringCoreMessages.RenameTypeParameterProcessor_descriptor_description_short, fTypeParameter.getElementName()); 277 final String header= Messages.format(RefactoringCoreMessages.RenameTypeParameterProcessor_descriptor_description, new String [] { fTypeParameter.getElementName(), JavaElementLabels.getElementLabel(fTypeParameter.getDeclaringMember(), JavaElementLabels.ALL_FULLY_QUALIFIED), getNewElementName()}); 278 final String comment= new JDTRefactoringDescriptorComment(project, this, header).asString(); 279 final RenameJavaElementDescriptor descriptor= new RenameJavaElementDescriptor(IJavaRefactorings.RENAME_TYPE_PARAMETER); 280 descriptor.setProject(project); 281 descriptor.setDescription(description); 282 descriptor.setComment(comment); 283 descriptor.setFlags(RefactoringDescriptor.NONE); 284 descriptor.setJavaElement(fTypeParameter); 285 descriptor.setNewName(getNewElementName()); 286 descriptor.setUpdateReferences(fUpdateReferences); 287 change= new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.RenameTypeParameterProcessor_change_name, new Change[] { change}); 288 } 289 return change; 290 } finally { 291 fChange= null; 292 monitor.done(); 293 } 294 } 295 296 305 private RefactoringStatus createRenameChanges(final IProgressMonitor monitor) throws CoreException { 306 Assert.isNotNull(monitor); 307 final RefactoringStatus status= new RefactoringStatus(); 308 try { 309 monitor.beginTask(RefactoringCoreMessages.RenameTypeParameterRefactoring_searching, 2); 310 final ICompilationUnit cu= fTypeParameter.getDeclaringMember().getCompilationUnit(); 311 final CompilationUnit root= RefactoringASTParser.parseWithASTProvider(cu, true, null); 312 final CompilationUnitRewrite rewrite= new CompilationUnitRewrite(cu, root); 313 final IMember member= fTypeParameter.getDeclaringMember(); 314 ASTNode declaration= null; 315 if (member instanceof IMethod) { 316 declaration= ASTNodeSearchUtil.getMethodDeclarationNode((IMethod) member, root); 317 } else if (member instanceof IType) { 318 declaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode((IType) member, root); 319 } else { 320 JavaPlugin.logErrorMessage("Unexpected sub-type of IMember: " + member.getClass().getName()); Assert.isTrue(false); 322 } 323 monitor.worked(1); 324 final RenameTypeParameterVisitor visitor= new RenameTypeParameterVisitor(rewrite, fTypeParameter.getNameRange(), status); 325 if (declaration != null) 326 declaration.accept(visitor); 327 fChange= visitor.getResult(); 328 } finally { 329 monitor.done(); 330 } 331 return status; 332 } 333 334 protected final String [] getAffectedProjectNatures() throws CoreException { 335 return JavaProcessors.computeAffectedNatures(fTypeParameter); 336 } 337 338 public final String getCurrentElementName() { 339 return fTypeParameter.getElementName(); 340 } 341 342 public final Object [] getElements() { 343 return new Object [] { fTypeParameter}; 344 } 345 346 public final String getIdentifier() { 347 return IDENTIFIER; 348 } 349 350 public final Object getNewElement() throws CoreException { 351 final IMember member= fTypeParameter.getDeclaringMember(); 352 if (member instanceof IType) { 353 final IType type= (IType) member; 354 return type.getTypeParameter(getNewElementName()); 355 } else if (member instanceof IMethod) { 356 final IMethod method= (IMethod) member; 357 return method.getTypeParameter(getNewElementName()); 358 } else { 359 JavaPlugin.logErrorMessage("Unexpected sub-type of IMember: " + member.getClass().getName()); Assert.isTrue(false); 361 } 362 return null; 363 } 364 365 public final String getProcessorName() { 366 return RefactoringCoreMessages.RenameTypeParameterProcessor_name; 367 } 368 369 public final boolean getUpdateReferences() { 370 return fUpdateReferences; 371 } 372 373 public final RefactoringStatus initialize(final RefactoringArguments arguments) { 374 if (arguments instanceof JavaRefactoringArguments) { 375 final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments; 376 final String parameter= extended.getAttribute(ATTRIBUTE_PARAMETER); 377 if (parameter == null || "".equals(parameter)) return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_PARAMETER)); 379 final String handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT); 380 if (handle != null) { 381 final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false); 382 if (element == null || !element.exists()) 383 return ScriptableRefactoring.createInputFatalStatus(element, getRefactoring().getName(), IJavaRefactorings.RENAME_TYPE_PARAMETER); 384 else { 385 if (element instanceof IMethod) 386 fTypeParameter= ((IMethod) element).getTypeParameter(parameter); 387 else if (element instanceof IType) 388 fTypeParameter= ((IType) element).getTypeParameter(parameter); 389 else 390 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new Object [] { handle, JDTRefactoringDescriptor.ATTRIBUTE_INPUT})); 391 if (fTypeParameter == null || !fTypeParameter.exists()) 392 return ScriptableRefactoring.createInputFatalStatus(fTypeParameter, getRefactoring().getName(), IJavaRefactorings.RENAME_TYPE_PARAMETER); 393 } 394 } else 395 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT)); 396 final String name= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_NAME); 397 if (name != null && !"".equals(name)) setNewElementName(name); 399 else 400 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_NAME)); 401 final String references= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_REFERENCES); 402 if (references != null) { 403 fUpdateReferences= Boolean.valueOf(references).booleanValue(); 404 } else 405 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_REFERENCES)); 406 } else 407 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments); 408 return new RefactoringStatus(); 409 } 410 411 public final boolean isApplicable() throws CoreException { 412 return RefactoringAvailabilityTester.isRenameAvailable(fTypeParameter); 413 } 414 415 public final void setUpdateReferences(final boolean update) { 416 fUpdateReferences= update; 417 } 418 } 419 | Popular Tags |