1 11 package org.eclipse.jdt.internal.corext.refactoring.structure; 12 13 import java.util.Collection ; 14 import java.util.HashSet ; 15 import java.util.Iterator ; 16 import java.util.Set ; 17 18 import org.eclipse.core.runtime.Assert; 19 import org.eclipse.core.runtime.CoreException; 20 import org.eclipse.core.runtime.IProgressMonitor; 21 import org.eclipse.core.runtime.NullProgressMonitor; 22 import org.eclipse.core.runtime.OperationCanceledException; 23 import org.eclipse.core.runtime.SubProgressMonitor; 24 25 import org.eclipse.ltk.core.refactoring.Change; 26 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; 27 import org.eclipse.ltk.core.refactoring.RefactoringStatus; 28 import org.eclipse.ltk.core.refactoring.TextChange; 29 import org.eclipse.ltk.core.refactoring.TextEditBasedChange; 30 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; 31 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments; 32 import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant; 33 import org.eclipse.ltk.core.refactoring.participants.SharableParticipants; 34 35 import org.eclipse.jdt.core.ICompilationUnit; 36 import org.eclipse.jdt.core.IJavaElement; 37 import org.eclipse.jdt.core.IJavaProject; 38 import org.eclipse.jdt.core.IType; 39 import org.eclipse.jdt.core.JavaModelException; 40 import org.eclipse.jdt.core.dom.AST; 41 import org.eclipse.jdt.core.dom.ASTNode; 42 import org.eclipse.jdt.core.dom.ASTParser; 43 import org.eclipse.jdt.core.dom.ASTRequestor; 44 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; 45 import org.eclipse.jdt.core.dom.CompilationUnit; 46 import org.eclipse.jdt.core.dom.IBinding; 47 import org.eclipse.jdt.core.dom.ITypeBinding; 48 import org.eclipse.jdt.core.refactoring.IJavaRefactorings; 49 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor; 50 import org.eclipse.jdt.core.refactoring.descriptors.UseSupertypeDescriptor; 51 52 import org.eclipse.jdt.internal.corext.dom.NodeFinder; 53 import org.eclipse.jdt.internal.corext.refactoring.Checks; 54 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor; 55 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment; 56 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments; 57 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; 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.structure.constraints.SuperTypeConstraintsModel; 61 import org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeConstraintsSolver; 62 import org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeRefactoringProcessor; 63 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType; 64 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ISourceConstraintVariable; 65 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeConstraintVariable; 66 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser; 67 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil; 68 import org.eclipse.jdt.internal.corext.refactoring.util.TextEditBasedChangeManager; 69 import org.eclipse.jdt.internal.corext.util.Messages; 70 71 import org.eclipse.jdt.ui.JavaElementLabels; 72 73 import org.eclipse.jdt.internal.ui.JavaPlugin; 74 75 78 public final class UseSuperTypeProcessor extends SuperTypeRefactoringProcessor { 79 80 private static final String IDENTIFIER= "org.eclipse.jdt.ui.useSuperTypeProcessor"; 82 92 protected static ITypeBinding findTypeInHierarchy(final ITypeBinding type, final String name) { 93 if (type.isArray() || type.isPrimitive()) 94 return null; 95 if (name.equals(type.getTypeDeclaration().getQualifiedName())) 96 return type; 97 final ITypeBinding binding= type.getSuperclass(); 98 if (binding != null) { 99 final ITypeBinding result= findTypeInHierarchy(binding, name); 100 if (result != null) 101 return result; 102 } 103 final ITypeBinding[] bindings= type.getInterfaces(); 104 for (int index= 0; index < bindings.length; index++) { 105 final ITypeBinding result= findTypeInHierarchy(bindings[index], name); 106 if (result != null) 107 return result; 108 } 109 return null; 110 } 111 112 113 private TextEditBasedChangeManager fChangeManager= null; 114 115 116 private int fChanges= 0; 117 118 119 private IType fSubType; 120 121 122 private IType fSuperType= null; 123 124 131 public UseSuperTypeProcessor(final IType subType) { 132 super(null); 133 fReplace= true; 134 fSubType= subType; 135 } 136 137 147 public UseSuperTypeProcessor(final IType subType, final IType superType) { 148 super(null); 149 fReplace= true; 150 fSubType= subType; 151 fSuperType= superType; 152 } 153 154 157 public final RefactoringStatus checkFinalConditions(final IProgressMonitor monitor, final CheckConditionsContext context) throws CoreException, OperationCanceledException { 158 Assert.isNotNull(monitor); 159 Assert.isNotNull(context); 160 final RefactoringStatus status= new RefactoringStatus(); 161 fChangeManager= new TextEditBasedChangeManager(); 162 try { 163 monitor.beginTask("", 200); monitor.setTaskName(RefactoringCoreMessages.UseSuperTypeProcessor_checking); 165 fChangeManager= createChangeManager(new SubProgressMonitor(monitor, 200), status); 166 if (!status.hasFatalError()) { 167 final RefactoringStatus validation= Checks.validateModifiesFiles(ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits()), getRefactoring().getValidationContext()); 168 if (!validation.isOK()) 169 return validation; 170 } 171 } finally { 172 monitor.done(); 173 } 174 return status; 175 } 176 177 180 public final RefactoringStatus checkInitialConditions(final IProgressMonitor monitor) throws CoreException, OperationCanceledException { 181 Assert.isNotNull(monitor); 182 final RefactoringStatus status= new RefactoringStatus(); 183 try { 184 monitor.beginTask("", 1); monitor.setTaskName(RefactoringCoreMessages.UseSuperTypeProcessor_checking); 186 monitor.worked(1); 188 } finally { 189 monitor.done(); 190 } 191 return status; 192 } 193 194 197 public final Change createChange(final IProgressMonitor monitor) throws CoreException, OperationCanceledException { 198 Assert.isNotNull(monitor); 199 try { 200 fChanges= 0; 201 monitor.beginTask("", 1); monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating); 203 final TextEditBasedChange[] changes= fChangeManager.getAllChanges(); 204 if (changes != null && changes.length != 0) { 205 fChanges= changes.length; 206 IJavaProject project= null; 207 if (!fSubType.isBinary()) 208 project= fSubType.getJavaProject(); 209 int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE | RefactoringDescriptor.MULTI_CHANGE; 210 try { 211 if (fSubType.isLocal() || fSubType.isAnonymous()) 212 flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT; 213 } catch (JavaModelException exception) { 214 JavaPlugin.log(exception); 215 } 216 final String name= project != null ? project.getElementName() : null; 217 final String description= Messages.format(RefactoringCoreMessages.UseSuperTypeProcessor_descriptor_description_short, fSuperType.getElementName()); 218 final String header= Messages.format(RefactoringCoreMessages.UseSuperTypeProcessor_descriptor_description, new String [] { JavaElementLabels.getElementLabel(fSuperType, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getElementLabel(fSubType, JavaElementLabels.ALL_FULLY_QUALIFIED) }); 219 final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(name, this, header); 220 comment.addSetting(Messages.format(RefactoringCoreMessages.UseSuperTypeProcessor_refactored_element_pattern, JavaElementLabels.getElementLabel(fSuperType, JavaElementLabels.ALL_FULLY_QUALIFIED))); 221 addSuperTypeSettings(comment, false); 222 final UseSupertypeDescriptor descriptor= new UseSupertypeDescriptor(); 223 descriptor.setProject(name); 224 descriptor.setDescription(description); 225 descriptor.setComment(comment.asString()); 226 descriptor.setFlags(flags); 227 descriptor.setSubtype(getSubType()); 228 descriptor.setSupertype(getSuperType()); 229 descriptor.setReplaceInstanceof(fInstanceOf); 230 return new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.UseSupertypeWherePossibleRefactoring_name, fChangeManager.getAllChanges()); 231 } 232 monitor.worked(1); 233 } finally { 234 monitor.done(); 235 } 236 return null; 237 } 238 239 252 protected final TextEditBasedChangeManager createChangeManager(final IProgressMonitor monitor, final RefactoringStatus status) throws JavaModelException, CoreException { 253 Assert.isNotNull(status); 254 Assert.isNotNull(monitor); 255 try { 256 monitor.beginTask("", 300); monitor.setTaskName(RefactoringCoreMessages.UseSuperTypeProcessor_creating); 258 final TextEditBasedChangeManager manager= new TextEditBasedChangeManager(); 259 final IJavaProject project= fSubType.getJavaProject(); 260 final ASTParser parser= ASTParser.newParser(AST.JLS3); 261 parser.setWorkingCopyOwner(fOwner); 262 parser.setResolveBindings(true); 263 parser.setProject(project); 264 parser.setCompilerOptions(RefactoringASTParser.getCompilerOptions(project)); 265 if (fSubType.isBinary() || fSubType.isReadOnly()) { 266 final IBinding[] bindings= parser.createBindings(new IJavaElement[] { fSubType, fSuperType }, new SubProgressMonitor(monitor, 50)); 267 if (bindings != null && bindings.length == 2 && bindings[0] instanceof ITypeBinding && bindings[1] instanceof ITypeBinding) { 268 solveSuperTypeConstraints(null, null, fSubType, (ITypeBinding) bindings[0], (ITypeBinding) bindings[1], new SubProgressMonitor(monitor, 100), status); 269 if (!status.hasFatalError()) 270 rewriteTypeOccurrences(manager, null, null, null, null, new HashSet (), status, new SubProgressMonitor(monitor, 150)); 271 } 272 } else { 273 parser.createASTs(new ICompilationUnit[] { fSubType.getCompilationUnit() }, new String [0], new ASTRequestor() { 274 275 public final void acceptAST(final ICompilationUnit unit, final CompilationUnit node) { 276 try { 277 final CompilationUnitRewrite subRewrite= new CompilationUnitRewrite(fOwner, unit, node); 278 final AbstractTypeDeclaration subDeclaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(fSubType, subRewrite.getRoot()); 279 if (subDeclaration != null) { 280 final ITypeBinding subBinding= subDeclaration.resolveBinding(); 281 if (subBinding != null) { 282 final ITypeBinding superBinding= findTypeInHierarchy(subBinding, fSuperType.getFullyQualifiedName('.')); 283 if (superBinding != null) { 284 solveSuperTypeConstraints(subRewrite.getCu(), subRewrite.getRoot(), fSubType, subBinding, superBinding, new SubProgressMonitor(monitor, 100), status); 285 if (!status.hasFatalError()) { 286 rewriteTypeOccurrences(manager, this, subRewrite, subRewrite.getCu(), subRewrite.getRoot(), new HashSet (), status, new SubProgressMonitor(monitor, 200)); 287 final TextChange change= subRewrite.createChange(); 288 if (change != null) 289 manager.manage(subRewrite.getCu(), change); 290 } 291 } 292 } 293 } 294 } catch (CoreException exception) { 295 JavaPlugin.log(exception); 296 status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.UseSuperTypeProcessor_internal_error)); 297 } 298 } 299 300 public final void acceptBinding(final String key, final IBinding binding) { 301 } 303 }, new NullProgressMonitor()); 304 } 305 return manager; 306 } finally { 307 monitor.done(); 308 } 309 } 310 311 314 protected final SuperTypeConstraintsSolver createContraintSolver(final SuperTypeConstraintsModel model) { 315 return new SuperTypeConstraintsSolver(model); 316 } 317 318 324 public final int getChanges() { 325 return fChanges; 326 } 327 328 331 public final Object [] getElements() { 332 return new Object [] { fSubType }; 333 } 334 335 338 public final String getIdentifier() { 339 return IDENTIFIER; 340 } 341 342 345 public final String getProcessorName() { 346 return RefactoringCoreMessages.UseSuperTypeProcessor_name; 347 } 348 349 354 public final IType getSubType() { 355 return fSubType; 356 } 357 358 363 public final IType getSuperType() { 364 return fSuperType; 365 } 366 367 370 public final RefactoringStatus initialize(final RefactoringArguments arguments) { 371 if (arguments instanceof JavaRefactoringArguments) { 372 final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments; 373 String handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT); 374 if (handle != null) { 375 final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false); 376 if (element == null || !element.exists() || element.getElementType() != IJavaElement.TYPE) 377 return ScriptableRefactoring.createInputFatalStatus(element, getRefactoring().getName(), IJavaRefactorings.USE_SUPER_TYPE); 378 else 379 fSubType= (IType) element; 380 } else 381 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT)); 382 handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + 1); 383 if (handle != null) { 384 final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false); 385 if (element == null || !element.exists() || element.getElementType() != IJavaElement.TYPE) 386 return ScriptableRefactoring.createInputFatalStatus(element, getRefactoring().getName(), IJavaRefactorings.USE_SUPER_TYPE); 387 else 388 fSuperType= (IType) element; 389 } else 390 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + 1)); 391 final String instance= extended.getAttribute(ATTRIBUTE_INSTANCEOF); 392 if (instance != null) { 393 fInstanceOf= Boolean.valueOf(instance).booleanValue(); 394 } else 395 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_INSTANCEOF)); 396 } else 397 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments); 398 return new RefactoringStatus(); 399 } 400 401 404 public final boolean isApplicable() throws CoreException { 405 return Checks.isAvailable(fSubType) && Checks.isAvailable(fSuperType) && !fSubType.isAnonymous() && !fSubType.isAnnotation() && !fSuperType.isAnonymous() && !fSuperType.isAnnotation() && !fSuperType.isEnum(); 406 } 407 408 411 public final RefactoringParticipant[] loadParticipants(final RefactoringStatus status, final SharableParticipants sharedParticipants) throws CoreException { 412 return new RefactoringParticipant[0]; 413 } 414 415 418 protected final void rewriteTypeOccurrences(final TextEditBasedChangeManager manager, final ASTRequestor requestor, final CompilationUnitRewrite rewrite, final ICompilationUnit unit, final CompilationUnit node, final Set replacements, final IProgressMonitor monitor) throws CoreException { 419 try { 420 monitor.beginTask("", 100); monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating); 422 final Collection collection= (Collection ) fTypeOccurrences.get(unit); 423 if (collection != null && !collection.isEmpty()) { 424 final IProgressMonitor subMonitor= new SubProgressMonitor(monitor, 100); 425 try { 426 subMonitor.beginTask("", collection.size() * 10); subMonitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating); 428 TType estimate= null; 429 ISourceConstraintVariable variable= null; 430 CompilationUnitRewrite currentRewrite= null; 431 final ICompilationUnit sourceUnit= rewrite.getCu(); 432 if (sourceUnit.equals(unit)) 433 currentRewrite= rewrite; 434 else 435 currentRewrite= new CompilationUnitRewrite(fOwner, unit, node); 436 for (final Iterator iterator= collection.iterator(); iterator.hasNext();) { 437 variable= (ISourceConstraintVariable) iterator.next(); 438 estimate= (TType) variable.getData(SuperTypeConstraintsSolver.DATA_TYPE_ESTIMATE); 439 if (estimate != null && variable instanceof ITypeConstraintVariable) { 440 final ASTNode result= NodeFinder.perform(node, ((ITypeConstraintVariable) variable).getRange().getSourceRange()); 441 if (result != null) 442 rewriteTypeOccurrence(estimate, currentRewrite, result, currentRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.SuperTypeRefactoringProcessor_update_type_occurrence, SET_SUPER_TYPE)); 443 } 444 subMonitor.worked(10); 445 } 446 if (!sourceUnit.equals(unit)) { 447 final TextChange change= currentRewrite.createChange(); 448 if (change != null) 449 manager.manage(unit, change); 450 } 451 } finally { 452 subMonitor.done(); 453 } 454 } 455 } finally { 456 monitor.done(); 457 } 458 } 459 460 466 public final void setSuperType(final IType type) { 467 Assert.isNotNull(type); 468 469 fSuperType= type; 470 } 471 } 472 | Popular Tags |