1 11 package org.eclipse.jdt.internal.corext.refactoring.structure; 12 13 import java.util.ArrayList ; 14 import java.util.Arrays ; 15 import java.util.Collection ; 16 import java.util.Comparator ; 17 import java.util.HashMap ; 18 import java.util.HashSet ; 19 import java.util.Iterator ; 20 import java.util.List ; 21 import java.util.Map ; 22 import java.util.Set ; 23 24 import org.eclipse.text.edits.MalformedTreeException; 25 import org.eclipse.text.edits.TextEdit; 26 27 import org.eclipse.core.runtime.Assert; 28 import org.eclipse.core.runtime.CoreException; 29 import org.eclipse.core.runtime.IProgressMonitor; 30 import org.eclipse.core.runtime.NullProgressMonitor; 31 import org.eclipse.core.runtime.OperationCanceledException; 32 import org.eclipse.core.runtime.SubProgressMonitor; 33 34 import org.eclipse.core.filebuffers.ITextFileBuffer; 35 36 import org.eclipse.core.resources.IFile; 37 38 import org.eclipse.jface.text.BadLocationException; 39 import org.eclipse.jface.text.Document; 40 import org.eclipse.jface.text.IDocument; 41 42 import org.eclipse.ltk.core.refactoring.Change; 43 import org.eclipse.ltk.core.refactoring.GroupCategory; 44 import org.eclipse.ltk.core.refactoring.GroupCategorySet; 45 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; 46 import org.eclipse.ltk.core.refactoring.RefactoringStatus; 47 import org.eclipse.ltk.core.refactoring.TextChange; 48 import org.eclipse.ltk.core.refactoring.TextEditBasedChange; 49 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; 50 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments; 51 import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant; 52 import org.eclipse.ltk.core.refactoring.participants.SharableParticipants; 53 54 import org.eclipse.jdt.core.ICompilationUnit; 55 import org.eclipse.jdt.core.IField; 56 import org.eclipse.jdt.core.IJavaElement; 57 import org.eclipse.jdt.core.IJavaProject; 58 import org.eclipse.jdt.core.IMember; 59 import org.eclipse.jdt.core.IMethod; 60 import org.eclipse.jdt.core.IPackageFragment; 61 import org.eclipse.jdt.core.ISourceReference; 62 import org.eclipse.jdt.core.IType; 63 import org.eclipse.jdt.core.ITypeParameter; 64 import org.eclipse.jdt.core.JavaCore; 65 import org.eclipse.jdt.core.JavaModelException; 66 import org.eclipse.jdt.core.dom.AST; 67 import org.eclipse.jdt.core.dom.ASTNode; 68 import org.eclipse.jdt.core.dom.ASTParser; 69 import org.eclipse.jdt.core.dom.ASTRequestor; 70 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; 71 import org.eclipse.jdt.core.dom.Annotation; 72 import org.eclipse.jdt.core.dom.CompilationUnit; 73 import org.eclipse.jdt.core.dom.EnumDeclaration; 74 import org.eclipse.jdt.core.dom.FieldDeclaration; 75 import org.eclipse.jdt.core.dom.IBinding; 76 import org.eclipse.jdt.core.dom.IExtendedModifier; 77 import org.eclipse.jdt.core.dom.IMethodBinding; 78 import org.eclipse.jdt.core.dom.ITypeBinding; 79 import org.eclipse.jdt.core.dom.IVariableBinding; 80 import org.eclipse.jdt.core.dom.MethodDeclaration; 81 import org.eclipse.jdt.core.dom.Modifier; 82 import org.eclipse.jdt.core.dom.ParameterizedType; 83 import org.eclipse.jdt.core.dom.SingleVariableDeclaration; 84 import org.eclipse.jdt.core.dom.Type; 85 import org.eclipse.jdt.core.dom.TypeDeclaration; 86 import org.eclipse.jdt.core.dom.VariableDeclarationFragment; 87 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; 88 import org.eclipse.jdt.core.dom.rewrite.ITrackedNodePosition; 89 import org.eclipse.jdt.core.dom.rewrite.ListRewrite; 90 import org.eclipse.jdt.core.refactoring.IJavaRefactorings; 91 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor; 92 93 import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings; 94 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility; 95 import org.eclipse.jdt.internal.corext.dom.Bindings; 96 import org.eclipse.jdt.internal.corext.dom.ModifierRewrite; 97 import org.eclipse.jdt.internal.corext.dom.NodeFinder; 98 import org.eclipse.jdt.internal.corext.refactoring.Checks; 99 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments; 100 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor; 101 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment; 102 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; 103 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext; 104 import org.eclipse.jdt.internal.corext.refactoring.changes.CreateCompilationUnitChange; 105 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange; 106 import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring; 107 import org.eclipse.jdt.internal.corext.refactoring.reorg.ASTNodeDeleteUtil; 108 import org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeConstraintsModel; 109 import org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeConstraintsSolver; 110 import org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeRefactoringProcessor; 111 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.CompilationUnitRange; 112 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType; 113 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ISourceConstraintVariable; 114 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeConstraintVariable; 115 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser; 116 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringFileBuffers; 117 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil; 118 import org.eclipse.jdt.internal.corext.refactoring.util.TextEditBasedChangeManager; 119 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 120 import org.eclipse.jdt.internal.corext.util.JdtFlags; 121 import org.eclipse.jdt.internal.corext.util.Messages; 122 import org.eclipse.jdt.internal.corext.util.Strings; 123 124 import org.eclipse.jdt.ui.CodeGeneration; 125 import org.eclipse.jdt.ui.JavaElementLabels; 126 127 import org.eclipse.jdt.internal.ui.JavaPlugin; 128 import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings; 129 130 133 public final class ExtractInterfaceProcessor extends SuperTypeRefactoringProcessor { 134 135 private static final String ATTRIBUTE_ABSTRACT= "abstract"; 137 private static final String ATTRIBUTE_COMMENTS= "comments"; 139 private static final String ATTRIBUTE_PUBLIC= "public"; 141 142 public static final String IDENTIFIER= "org.eclipse.jdt.ui.extractInterfaceProcessor"; 144 145 private static final GroupCategorySet SET_EXTRACT_INTERFACE= new GroupCategorySet(new GroupCategory("org.eclipse.jdt.internal.corext.extractInterface", RefactoringCoreMessages.ExtractInterfaceProcessor_category_name, RefactoringCoreMessages.ExtractInterfaceProcessor_category_description)); 147 148 158 protected static boolean isExtractableMember(final IMember member) throws JavaModelException { 159 Assert.isNotNull(member); 160 switch (member.getElementType()) { 161 case IJavaElement.METHOD: 162 return JdtFlags.isPublic(member) && !JdtFlags.isStatic(member) && !((IMethod) member).isConstructor(); 163 case IJavaElement.FIELD: 164 return JdtFlags.isPublic(member) && JdtFlags.isStatic(member) && JdtFlags.isFinal(member) && !JdtFlags.isEnum(member); 165 default: 166 return false; 167 } 168 } 169 170 171 private boolean fAbstract= true; 172 173 174 private TextEditBasedChangeManager fChangeManager= null; 175 176 177 private boolean fComments= true; 178 179 180 private IMember[] fMembers= null; 181 182 183 private boolean fPublic= true; 184 185 186 private IType fSubType; 187 188 189 private String fSuperName; 190 191 192 private String fSuperSource= null; 193 194 204 public ExtractInterfaceProcessor(final IType type, final CodeGenerationSettings settings) { 205 super(settings); 206 fSubType= type; 207 if (fSubType != null) 208 fSuperName= fSubType.getElementName(); 209 } 210 211 214 public final RefactoringStatus checkFinalConditions(final IProgressMonitor monitor, final CheckConditionsContext context) throws CoreException, OperationCanceledException { 215 Assert.isNotNull(monitor); 216 Assert.isNotNull(context); 217 final RefactoringStatus status= new RefactoringStatus(); 218 fChangeManager= new TextEditBasedChangeManager(); 219 try { 220 monitor.beginTask("", 1); monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_checking); 222 status.merge(Checks.checkIfCuBroken(fSubType)); 223 if (!status.hasError()) { 224 if (fSubType.isBinary() || fSubType.isReadOnly() || !fSubType.exists()) 225 status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_no_binary, JavaStatusContext.create(fSubType))); 226 else if (fSubType.isAnonymous()) 227 status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_no_anonymous, JavaStatusContext.create(fSubType))); 228 else if (fSubType.isAnnotation()) 229 status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_no_annotation, JavaStatusContext.create(fSubType))); 230 else { 231 status.merge(checkSuperType()); 232 if (!status.hasFatalError()) { 233 if (!status.hasFatalError()) { 234 fChangeManager= createChangeManager(new SubProgressMonitor(monitor, 1), status); 235 if (!status.hasFatalError()) { 236 final RefactoringStatus validation= Checks.validateModifiesFiles(ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits()), getRefactoring().getValidationContext()); 237 if (!validation.isOK()) 238 return validation; 239 } 240 } 241 } 242 } 243 } 244 } finally { 245 monitor.done(); 246 } 247 return status; 248 } 249 250 253 public final RefactoringStatus checkInitialConditions(final IProgressMonitor monitor) throws CoreException, OperationCanceledException { 254 Assert.isNotNull(monitor); 255 final RefactoringStatus status= new RefactoringStatus(); 256 try { 257 monitor.beginTask("", 1); monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_checking); 259 status.merge(Checks.checkIfCuBroken(fSubType)); 260 monitor.worked(1); 261 } finally { 262 monitor.done(); 263 } 264 return status; 265 } 266 267 274 protected final RefactoringStatus checkSuperType() throws JavaModelException { 275 final IPackageFragment fragment= fSubType.getPackageFragment(); 276 final IType type= Checks.findTypeInPackage(fragment, fSuperName); 277 if (type != null && type.exists()) { 278 if (fragment.isDefaultPackage()) 279 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.ExtractInterfaceProcessor_existing_default_type, new String [] { fSuperName })); 280 else 281 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.ExtractInterfaceProcessor_existing_type, new String [] { fSuperName, fragment.getElementName() })); 282 } 283 return new RefactoringStatus(); 284 } 285 286 293 public final RefactoringStatus checkTypeName(final String name) { 294 Assert.isNotNull(name); 295 try { 296 final RefactoringStatus result= Checks.checkTypeName(name); 297 if (result.hasFatalError()) 298 return result; 299 final String unitName= JavaModelUtil.getRenamedCUName(fSubType.getCompilationUnit(), name); 300 result.merge(Checks.checkCompilationUnitName(unitName)); 301 if (result.hasFatalError()) 302 return result; 303 final IPackageFragment fragment= fSubType.getPackageFragment(); 304 if (fragment.getCompilationUnit(unitName).exists()) { 305 result.addFatalError(Messages.format(RefactoringCoreMessages.ExtractInterfaceProcessor_existing_compilation_unit, new String [] { unitName, fragment.getElementName() })); 306 return result; 307 } 308 result.merge(checkSuperType()); 309 return result; 310 } catch (JavaModelException exception) { 311 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_internal_error); 312 } 313 } 314 315 318 public final Change createChange(final IProgressMonitor monitor) throws CoreException, OperationCanceledException { 319 Assert.isNotNull(monitor); 320 try { 321 monitor.beginTask("", 1); monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating); 323 final Map arguments= new HashMap (); 324 String project= null; 325 final IJavaProject javaProject= fSubType.getJavaProject(); 326 if (javaProject != null) 327 project= javaProject.getElementName(); 328 int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE | RefactoringDescriptor.MULTI_CHANGE; 329 try { 330 if (fSubType.isLocal() || fSubType.isAnonymous()) 331 flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT; 332 } catch (JavaModelException exception) { 333 JavaPlugin.log(exception); 334 } 335 final IPackageFragment fragment= fSubType.getPackageFragment(); 336 final ICompilationUnit cu= fragment.getCompilationUnit(JavaModelUtil.getRenamedCUName(fSubType.getCompilationUnit(), fSuperName)); 337 final IType type= cu.getType(fSuperName); 338 final String description= Messages.format(RefactoringCoreMessages.ExtractInterfaceProcessor_description_descriptor_short, fSuperName); 339 final String header= Messages.format(RefactoringCoreMessages.ExtractInterfaceProcessor_descriptor_description, new String [] { JavaElementLabels.getElementLabel(type, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getElementLabel(fSubType, JavaElementLabels.ALL_FULLY_QUALIFIED) }); 340 final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header); 341 comment.addSetting(Messages.format(RefactoringCoreMessages.ExtractInterfaceProcessor_refactored_element_pattern, JavaElementLabels.getElementLabel(type, JavaElementLabels.ALL_FULLY_QUALIFIED))); 342 final String [] settings= new String [fMembers.length]; 343 for (int index= 0; index < settings.length; index++) 344 settings[index]= JavaElementLabels.getElementLabel(fMembers[index], JavaElementLabels.ALL_FULLY_QUALIFIED); 345 comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ExtractInterfaceProcessor_extracted_members_pattern, settings)); 346 addSuperTypeSettings(comment, true); 347 final JDTRefactoringDescriptor descriptor= new JDTRefactoringDescriptor(IJavaRefactorings.EXTRACT_INTERFACE, project, description, comment.asString(), arguments, flags); 348 arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_INPUT, descriptor.elementToHandle(fSubType)); 349 arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_NAME, fSuperName); 350 for (int index= 0; index < fMembers.length; index++) 351 arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + (index + 1), descriptor.elementToHandle(fMembers[index])); 352 arguments.put(ATTRIBUTE_ABSTRACT, Boolean.valueOf(fAbstract).toString()); 353 arguments.put(ATTRIBUTE_COMMENTS, Boolean.valueOf(fComments).toString()); 354 arguments.put(ATTRIBUTE_PUBLIC, Boolean.valueOf(fPublic).toString()); 355 arguments.put(ATTRIBUTE_REPLACE, Boolean.valueOf(fReplace).toString()); 356 arguments.put(ATTRIBUTE_INSTANCEOF, Boolean.valueOf(fInstanceOf).toString()); 357 final DynamicValidationRefactoringChange change= new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.ExtractInterfaceRefactoring_name, fChangeManager.getAllChanges()); 358 final IFile file= ResourceUtil.getFile(fSubType.getCompilationUnit()); 359 if (fSuperSource != null && fSuperSource.length() > 0) 360 change.add(new CreateCompilationUnitChange(fSubType.getPackageFragment().getCompilationUnit(JavaModelUtil.getRenamedCUName(fSubType.getCompilationUnit(), fSuperName)), fSuperSource, file.getCharset(false))); 361 monitor.worked(1); 362 return change; 363 } finally { 364 monitor.done(); 365 } 366 } 367 368 381 protected final TextEditBasedChangeManager createChangeManager(final IProgressMonitor monitor, final RefactoringStatus status) throws JavaModelException, CoreException { 382 Assert.isNotNull(status); 383 Assert.isNotNull(monitor); 384 try { 385 monitor.beginTask("", 300); monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating); 387 resetEnvironment(); 388 final TextEditBasedChangeManager manager= new TextEditBasedChangeManager(); 389 final CompilationUnitRewrite sourceRewrite= new CompilationUnitRewrite(fSubType.getCompilationUnit()); 390 final AbstractTypeDeclaration declaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(fSubType, sourceRewrite.getRoot()); 391 if (declaration != null) { 392 createTypeSignature(sourceRewrite, declaration, status, new SubProgressMonitor(monitor, 20)); 393 final IField[] fields= getExtractedFields(fSubType.getCompilationUnit()); 394 if (fields.length > 0) 395 ASTNodeDeleteUtil.markAsDeleted(fields, sourceRewrite, sourceRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.ExtractInterfaceProcessor_remove_field_label, SET_EXTRACT_INTERFACE)); 396 if (fSubType.isInterface()) { 397 final IMethod[] methods= getExtractedMethods(fSubType.getCompilationUnit()); 398 if (methods.length > 0) 399 ASTNodeDeleteUtil.markAsDeleted(methods, sourceRewrite, sourceRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.ExtractInterfaceProcessor_remove_method_label, SET_EXTRACT_INTERFACE)); 400 } 401 final String name= JavaModelUtil.getRenamedCUName(fSubType.getCompilationUnit(), fSuperName); 402 final ICompilationUnit original= fSubType.getPackageFragment().getCompilationUnit(name); 403 final ICompilationUnit copy= getSharedWorkingCopy(original.getPrimary(), new SubProgressMonitor(monitor, 20)); 404 fSuperSource= createTypeSource(copy, fSubType, fSuperName, sourceRewrite, declaration, status, new SubProgressMonitor(monitor, 40)); 405 if (fSuperSource != null) { 406 copy.getBuffer().setContents(fSuperSource); 407 JavaModelUtil.reconcile(copy); 408 } 409 final Set replacements= new HashSet (); 410 if (fReplace) 411 rewriteTypeOccurrences(manager, sourceRewrite, copy, replacements, status, new SubProgressMonitor(monitor, 220)); 412 createMethodComments(sourceRewrite, replacements); 413 manager.manage(fSubType.getCompilationUnit(), sourceRewrite.createChange()); 414 } 415 return manager; 416 } finally { 417 monitor.done(); 418 } 419 } 420 421 424 protected final SuperTypeConstraintsSolver createContraintSolver(final SuperTypeConstraintsModel model) { 425 return new ExtractInterfaceConstraintsSolver(model, fSuperName); 426 } 427 428 442 protected final void createFieldDeclaration(final CompilationUnitRewrite sourceRewrite, final ASTRewrite targetRewrite, final AbstractTypeDeclaration targetDeclaration, final VariableDeclarationFragment fragment) throws CoreException { 443 Assert.isNotNull(targetDeclaration); 444 Assert.isNotNull(sourceRewrite); 445 Assert.isNotNull(targetRewrite); 446 Assert.isNotNull(fragment); 447 final FieldDeclaration field= (FieldDeclaration) fragment.getParent(); 448 ImportRewriteUtil.collectImports(fSubType.getJavaProject(), field, fTypeBindings, fStaticBindings, false); 449 final ASTRewrite rewrite= ASTRewrite.create(field.getAST()); 450 final ITrackedNodePosition position= rewrite.track(field); 451 final ListRewrite rewriter= rewrite.getListRewrite(field, FieldDeclaration.FRAGMENTS_PROPERTY); 452 VariableDeclarationFragment current= null; 453 for (final Iterator iterator= field.fragments().iterator(); iterator.hasNext();) { 454 current= (VariableDeclarationFragment) iterator.next(); 455 if (!current.getName().getIdentifier().equals(fragment.getName().getIdentifier())) 456 rewriter.remove(current, null); 457 } 458 final ICompilationUnit unit= sourceRewrite.getCu(); 459 final ITextFileBuffer buffer= RefactoringFileBuffers.acquire(unit); 460 try { 461 final IDocument document= new Document(buffer.getDocument().get()); 462 try { 463 rewrite.rewriteAST(document, unit.getJavaProject().getOptions(true)).apply(document, TextEdit.UPDATE_REGIONS); 464 targetRewrite.getListRewrite(targetDeclaration, targetDeclaration.getBodyDeclarationsProperty()).insertFirst(targetRewrite.createStringPlaceholder(normalizeText(document.get(position.getStartPosition(), position.getLength())), ASTNode.FIELD_DECLARATION), null); 465 } catch (MalformedTreeException exception) { 466 JavaPlugin.log(exception); 467 } catch (BadLocationException exception) { 468 JavaPlugin.log(exception); 469 } 470 } finally { 471 RefactoringFileBuffers.release(unit); 472 } 473 } 474 475 478 protected final void createMemberDeclarations(final CompilationUnitRewrite sourceRewrite, final ASTRewrite targetRewrite, final AbstractTypeDeclaration targetDeclaration) throws CoreException { 479 Assert.isNotNull(sourceRewrite); 480 Assert.isNotNull(targetRewrite); 481 Assert.isNotNull(targetDeclaration); 482 Arrays.sort(fMembers, new Comparator () { 483 484 public final int compare(final Object first, final Object second) { 485 Assert.isNotNull(first); 486 Assert.isNotNull(second); 487 final ISourceReference predecessor= (ISourceReference) first; 488 final ISourceReference successor= (ISourceReference) second; 489 try { 490 return predecessor.getSourceRange().getOffset() - successor.getSourceRange().getOffset(); 491 } catch (JavaModelException exception) { 492 return first.hashCode() - second.hashCode(); 493 } 494 } 495 }); 496 fTypeBindings.clear(); 497 fStaticBindings.clear(); 498 if (fMembers.length > 0) { 499 IMember member= null; 500 for (int index= fMembers.length - 1; index >= 0; index--) { 501 member= fMembers[index]; 502 if (member instanceof IField) { 503 createFieldDeclaration(sourceRewrite, targetRewrite, targetDeclaration, ASTNodeSearchUtil.getFieldDeclarationFragmentNode((IField) member, sourceRewrite.getRoot())); 504 } else if (member instanceof IMethod) { 505 createMethodDeclaration(sourceRewrite, targetRewrite, targetDeclaration, ASTNodeSearchUtil.getMethodDeclarationNode((IMethod) member, sourceRewrite.getRoot())); 506 } 507 } 508 } 509 } 510 511 527 protected final void createMethodComment(final CompilationUnitRewrite sourceRewrite, final MethodDeclaration declaration, final Set replacements, final boolean javadoc) throws CoreException { 528 Assert.isNotNull(sourceRewrite); 529 Assert.isNotNull(declaration); 530 Assert.isNotNull(replacements); 531 final IMethodBinding binding= declaration.resolveBinding(); 532 if (binding != null) { 533 IVariableBinding variable= null; 534 SingleVariableDeclaration argument= null; 535 final IPackageFragment fragment= fSubType.getPackageFragment(); 536 final String string= fragment.isDefaultPackage() ? fSuperName : fragment.getElementName() + "." + fSuperName; final ITypeBinding[] bindings= binding.getParameterTypes(); 538 final String [] names= new String [bindings.length]; 539 for (int offset= 0; offset < names.length; offset++) { 540 argument= (SingleVariableDeclaration) declaration.parameters().get(offset); 541 variable= argument.resolveBinding(); 542 if (variable != null) { 543 if (replacements.contains(variable.getKey())) 544 names[offset]= string; 545 else { 546 if (binding.isVarargs() && bindings[offset].isArray() && offset == names.length - 1) 547 names[offset]= Bindings.getFullyQualifiedName(bindings[offset].getElementType()); 548 else 549 names[offset]= Bindings.getFullyQualifiedName(bindings[offset]); 550 } 551 } 552 } 553 final String comment= CodeGeneration.getMethodComment(fSubType.getCompilationUnit(), fSubType.getElementName(), declaration, false, binding.getName(), string, names, StubUtility.getLineDelimiterUsed(fSubType.getJavaProject())); 554 if (comment != null) { 555 final ASTRewrite rewrite= sourceRewrite.getASTRewrite(); 556 if (declaration.getJavadoc() != null) { 557 rewrite.replace(declaration.getJavadoc(), rewrite.createStringPlaceholder(comment, ASTNode.JAVADOC), sourceRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.ExtractInterfaceProcessor_rewrite_comment, SET_EXTRACT_INTERFACE)); 558 } else if (javadoc) { 559 rewrite.set(declaration, MethodDeclaration.JAVADOC_PROPERTY, rewrite.createStringPlaceholder(comment, ASTNode.JAVADOC), sourceRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.ExtractInterfaceProcessor_add_comment, SET_EXTRACT_INTERFACE)); 560 } 561 } 562 } 563 } 564 565 577 protected final void createMethodComments(final CompilationUnitRewrite sourceRewrite, final Set replacements) throws CoreException { 578 Assert.isNotNull(sourceRewrite); 579 Assert.isNotNull(replacements); 580 if (fComments && fMembers.length > 0) { 581 final IJavaProject project= fSubType.getJavaProject(); 582 final boolean javadoc= project.getOption(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, true).equals(JavaCore.ENABLED); 583 IMember member= null; 584 for (int index= 0; index < fMembers.length; index++) { 585 member= fMembers[index]; 586 if (member instanceof IMethod) 587 createMethodComment(sourceRewrite, ASTNodeSearchUtil.getMethodDeclarationNode((IMethod) member, sourceRewrite.getRoot()), replacements, javadoc); 588 } 589 } 590 } 591 592 606 protected final void createMethodDeclaration(final CompilationUnitRewrite sourceRewrite, final ASTRewrite targetRewrite, final AbstractTypeDeclaration targetDeclaration, final MethodDeclaration declaration) throws CoreException { 607 Assert.isNotNull(targetDeclaration); 608 Assert.isNotNull(sourceRewrite); 609 Assert.isNotNull(targetRewrite); 610 Assert.isNotNull(declaration); 611 ImportRewriteUtil.collectImports(fSubType.getJavaProject(), declaration, fTypeBindings, fStaticBindings, true); 612 final ASTRewrite rewrite= ASTRewrite.create(declaration.getAST()); 613 final ITrackedNodePosition position= rewrite.track(declaration); 614 if (declaration.getBody() != null) 615 rewrite.remove(declaration.getBody(), null); 616 final ListRewrite list= rewrite.getListRewrite(declaration, declaration.getModifiersProperty()); 617 boolean publicFound= false; 618 boolean abstractFound= false; 619 ITypeBinding binding= null; 620 Modifier modifier= null; 621 Annotation annotation= null; 622 IExtendedModifier extended= null; 623 for (final Iterator iterator= declaration.modifiers().iterator(); iterator.hasNext();) { 624 extended= (IExtendedModifier) iterator.next(); 625 if (!extended.isAnnotation()) { 626 modifier= (Modifier) extended; 627 if (fPublic && modifier.getKeyword().equals(Modifier.ModifierKeyword.PUBLIC_KEYWORD)) { 628 publicFound= true; 629 continue; 630 } 631 if (fAbstract && modifier.getKeyword().equals(Modifier.ModifierKeyword.ABSTRACT_KEYWORD)) { 632 abstractFound= true; 633 continue; 634 } 635 list.remove(modifier, null); 636 } else if (extended.isAnnotation()) { 637 annotation= (Annotation) extended; 638 binding= annotation.resolveTypeBinding(); 639 if (binding.getQualifiedName().equals("java.lang.Override")) list.remove(annotation, null); 641 } 642 } 643 final ModifierRewrite rewriter= ModifierRewrite.create(rewrite, declaration); 644 if (fPublic && !publicFound) 645 rewriter.setVisibility(Modifier.PUBLIC, null); 646 if (fAbstract && !abstractFound) 647 rewriter.setModifiers(Modifier.ABSTRACT, 0, null); 648 final ICompilationUnit unit= sourceRewrite.getCu(); 649 final ITextFileBuffer buffer= RefactoringFileBuffers.acquire(unit); 650 try { 651 final IDocument document= new Document(buffer.getDocument().get()); 652 try { 653 rewrite.rewriteAST(document, unit.getJavaProject().getOptions(true)).apply(document, TextEdit.UPDATE_REGIONS); 654 targetRewrite.getListRewrite(targetDeclaration, targetDeclaration.getBodyDeclarationsProperty()).insertFirst(targetRewrite.createStringPlaceholder(normalizeText(document.get(position.getStartPosition(), position.getLength())), ASTNode.METHOD_DECLARATION), null); 655 } catch (MalformedTreeException exception) { 656 JavaPlugin.log(exception); 657 } catch (BadLocationException exception) { 658 JavaPlugin.log(exception); 659 } 660 } finally { 661 RefactoringFileBuffers.release(unit); 662 } 663 } 664 665 679 protected final void createTypeSignature(final CompilationUnitRewrite rewrite, final AbstractTypeDeclaration declaration, final RefactoringStatus status, final IProgressMonitor monitor) throws JavaModelException { 680 Assert.isNotNull(rewrite); 681 Assert.isNotNull(declaration); 682 Assert.isNotNull(status); 683 Assert.isNotNull(monitor); 684 try { 685 monitor.beginTask("", 1); monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating); 687 final AST ast= declaration.getAST(); 688 final ITypeParameter[] parameters= fSubType.getTypeParameters(); 689 Type type= ast.newSimpleType(ast.newSimpleName(fSuperName)); 690 if (parameters.length > 0) { 691 final ParameterizedType parameterized= ast.newParameterizedType(type); 692 for (int index= 0; index < parameters.length; index++) 693 parameterized.typeArguments().add(ast.newSimpleType(ast.newSimpleName(parameters[index].getElementName()))); 694 type= parameterized; 695 } 696 final ASTRewrite rewriter= rewrite.getASTRewrite(); 697 if (declaration instanceof TypeDeclaration) 698 rewriter.getListRewrite(declaration, TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY).insertLast(type, rewrite.createCategorizedGroupDescription(RefactoringCoreMessages.ExtractInterfaceProcessor_add_super_interface, SET_EXTRACT_INTERFACE)); 699 else if (declaration instanceof EnumDeclaration) 700 rewriter.getListRewrite(declaration, EnumDeclaration.SUPER_INTERFACE_TYPES_PROPERTY).insertLast(type, rewrite.createCategorizedGroupDescription(RefactoringCoreMessages.ExtractInterfaceProcessor_add_super_interface, SET_EXTRACT_INTERFACE)); 701 monitor.worked(1); 702 } finally { 703 monitor.done(); 704 } 705 } 706 707 713 public final boolean getAbstract() { 714 return fAbstract; 715 } 716 717 720 public final Object [] getElements() { 721 return new Object [] { fSubType }; 722 } 723 724 731 public final IMember[] getExtractableMembers() throws JavaModelException { 732 final List list= new ArrayList (); 733 IJavaElement[] children= fSubType.getChildren(); 734 for (int index= 0; index < children.length; index++) { 735 if (children[index] instanceof IMember && isExtractableMember((IMember) children[index])) 736 list.add(children[index]); 737 } 738 final IMember[] members= new IMember[list.size()]; 739 list.toArray(members); 740 return members; 741 } 742 743 750 protected final IField[] getExtractedFields(final ICompilationUnit unit) { 751 Assert.isNotNull(unit); 752 final List list= new ArrayList (); 753 for (int index= 0; index < fMembers.length; index++) { 754 if (fMembers[index] instanceof IField) { 755 final IJavaElement element= JavaModelUtil.findInCompilationUnit(unit, fMembers[index]); 756 if (element instanceof IField) 757 list.add(element); 758 } 759 } 760 final IField[] fields= new IField[list.size()]; 761 list.toArray(fields); 762 return fields; 763 } 764 765 772 protected final IMethod[] getExtractedMethods(final ICompilationUnit unit) { 773 Assert.isNotNull(unit); 774 final List list= new ArrayList (); 775 for (int index= 0; index < fMembers.length; index++) { 776 if (fMembers[index] instanceof IMethod) { 777 final IJavaElement element= JavaModelUtil.findInCompilationUnit(unit, fMembers[index]); 778 if (element instanceof IMethod) 779 list.add(element); 780 } 781 } 782 final IMethod[] methods= new IMethod[list.size()]; 783 list.toArray(methods); 784 return methods; 785 } 786 787 790 public final String getIdentifier() { 791 return IDENTIFIER; 792 } 793 794 797 public final String getProcessorName() { 798 return RefactoringCoreMessages.ExtractInterfaceProcessor_name; 799 } 800 801 807 public final boolean getPublic() { 808 return fPublic; 809 } 810 811 816 public final IType getType() { 817 return fSubType; 818 } 819 820 825 public final String getTypeName() { 826 return fSuperName; 827 } 828 829 832 public final RefactoringStatus initialize(final RefactoringArguments arguments) { 833 if (arguments instanceof JavaRefactoringArguments) { 834 final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments; 835 String handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT); 836 if (handle != null) { 837 final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false); 838 if (element == null || !element.exists() || element.getElementType() != IJavaElement.TYPE) 839 return ScriptableRefactoring.createInputFatalStatus(element, getRefactoring().getName(), IJavaRefactorings.EXTRACT_INTERFACE); 840 else 841 fSubType= (IType) element; 842 } else 843 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT)); 844 final String name= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_NAME); 845 if (name != null) { 846 fSuperName= name; 847 final RefactoringStatus status= checkTypeName(name); 848 if (status.hasError()) 849 return status; 850 } else 851 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_NAME)); 852 final String deferred= extended.getAttribute(ATTRIBUTE_ABSTRACT); 853 if (deferred != null) { 854 fAbstract= Boolean.valueOf(deferred).booleanValue(); 855 } else 856 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_ABSTRACT)); 857 final String comment= extended.getAttribute(ATTRIBUTE_COMMENTS); 858 if (comment != null) { 859 fComments= Boolean.valueOf(comment).booleanValue(); 860 } else 861 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_COMMENTS)); 862 final String instance= extended.getAttribute(ATTRIBUTE_INSTANCEOF); 863 if (instance != null) { 864 fInstanceOf= Boolean.valueOf(instance).booleanValue(); 865 } else 866 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_INSTANCEOF)); 867 final String visibility= extended.getAttribute(ATTRIBUTE_PUBLIC); 868 if (visibility != null) { 869 fPublic= Boolean.valueOf(visibility).booleanValue(); 870 } else 871 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_PUBLIC)); 872 final String replace= extended.getAttribute(ATTRIBUTE_REPLACE); 873 if (replace != null) { 874 fReplace= Boolean.valueOf(replace).booleanValue(); 875 } else 876 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_REPLACE)); 877 int count= 1; 878 final List elements= new ArrayList (); 879 String attribute= JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + count; 880 final RefactoringStatus status= new RefactoringStatus(); 881 while ((handle= extended.getAttribute(attribute)) != null) { 882 final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false); 883 if (element == null || !element.exists()) 884 status.merge(ScriptableRefactoring.createInputWarningStatus(element, getRefactoring().getName(), IJavaRefactorings.EXTRACT_INTERFACE)); 885 else 886 elements.add(element); 887 count++; 888 attribute= JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + count; 889 } 890 fMembers= (IMember[]) elements.toArray(new IMember[elements.size()]); 891 fSettings= JavaPreferencesSettings.getCodeGenerationSettings(fSubType.getJavaProject()); 892 if (!status.isOK()) 893 return status; 894 } else 895 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments); 896 return new RefactoringStatus(); 897 } 898 899 902 public final boolean isApplicable() throws CoreException { 903 return Checks.isAvailable(fSubType) && !fSubType.isBinary() && !fSubType.isReadOnly() && !fSubType.isAnnotation() && !fSubType.isAnonymous(); 904 } 905 906 912 public final boolean isComments() { 913 return fComments; 914 } 915 916 919 public final RefactoringParticipant[] loadParticipants(final RefactoringStatus status, final SharableParticipants sharedParticipants) throws CoreException { 920 return new RefactoringParticipant[0]; 921 } 922 923 932 protected final String normalizeText(final String code) throws JavaModelException { 933 Assert.isNotNull(code); 934 final String [] lines= Strings.convertIntoLines(code); 935 final IJavaProject project= fSubType.getJavaProject(); 936 Strings.trimIndentation(lines, project, false); 937 return Strings.concatenate(lines, StubUtility.getLineDelimiterUsed(project)); 938 } 939 940 943 protected void resetEnvironment() { 944 fSuperSource= null; 945 resetWorkingCopies(); 946 } 947 948 951 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 { 952 try { 953 monitor.beginTask("", 100); monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating); 955 CompilationUnitRewrite currentRewrite= null; 956 final boolean isSubUnit= rewrite.getCu().equals(unit.getPrimary()); 957 if (isSubUnit) 958 currentRewrite= rewrite; 959 else 960 currentRewrite= new CompilationUnitRewrite(unit, node); 961 final Collection collection= (Collection ) fTypeOccurrences.get(unit); 962 if (collection != null && !collection.isEmpty()) { 963 final IProgressMonitor subMonitor= new SubProgressMonitor(monitor, 100); 964 try { 965 subMonitor.beginTask("", collection.size() * 10); subMonitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating); 967 TType estimate= null; 968 ISourceConstraintVariable variable= null; 969 ITypeConstraintVariable constraint= null; 970 for (final Iterator iterator= collection.iterator(); iterator.hasNext();) { 971 variable= (ISourceConstraintVariable) iterator.next(); 972 if (variable instanceof ITypeConstraintVariable) { 973 constraint= (ITypeConstraintVariable) variable; 974 estimate= (TType) constraint.getData(SuperTypeConstraintsSolver.DATA_TYPE_ESTIMATE); 975 if (estimate != null) { 976 final CompilationUnitRange range= constraint.getRange(); 977 if (isSubUnit) 978 rewriteTypeOccurrence(range, estimate, requestor, currentRewrite, node, replacements, currentRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.SuperTypeRefactoringProcessor_update_type_occurrence, SET_SUPER_TYPE)); 979 else { 980 final ASTNode result= NodeFinder.perform(node, range.getSourceRange()); 981 if (result != null) 982 rewriteTypeOccurrence(estimate, currentRewrite, result, currentRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.SuperTypeRefactoringProcessor_update_type_occurrence, SET_SUPER_TYPE)); 983 } 984 subMonitor.worked(10); 985 } 986 } 987 } 988 } finally { 989 subMonitor.done(); 990 } 991 } 992 if (!isSubUnit) { 993 final TextChange change= currentRewrite.createChange(); 994 if (change != null) 995 manager.manage(unit, change); 996 } 997 } finally { 998 monitor.done(); 999 } 1000 } 1001 1002 1022 protected final void rewriteTypeOccurrences(final TextEditBasedChangeManager manager, final CompilationUnitRewrite sourceRewrite, final ICompilationUnit superUnit, final Set replacements, final RefactoringStatus status, final IProgressMonitor monitor) throws CoreException { 1023 Assert.isNotNull(manager); 1024 Assert.isNotNull(sourceRewrite); 1025 Assert.isNotNull(superUnit); 1026 Assert.isNotNull(replacements); 1027 Assert.isNotNull(status); 1028 Assert.isNotNull(monitor); 1029 try { 1030 monitor.beginTask("", 300); monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating); 1032 final ICompilationUnit subUnit= getSharedWorkingCopy(fSubType.getCompilationUnit().getPrimary(), new SubProgressMonitor(monitor, 20)); 1033 final ITextFileBuffer buffer= RefactoringFileBuffers.acquire(fSubType.getCompilationUnit()); 1034 final ASTRewrite rewrite= sourceRewrite.getASTRewrite(); 1035 try { 1036 final IDocument document= new Document(buffer.getDocument().get()); 1037 try { 1038 rewrite.rewriteAST(document, fSubType.getJavaProject().getOptions(true)).apply(document, TextEdit.UPDATE_REGIONS); 1039 } catch (MalformedTreeException exception) { 1040 JavaPlugin.log(exception); 1041 } catch (BadLocationException exception) { 1042 JavaPlugin.log(exception); 1043 } 1044 subUnit.getBuffer().setContents(document.get()); 1045 } finally { 1046 RefactoringFileBuffers.release(fSubType.getCompilationUnit()); 1047 } 1048 JavaModelUtil.reconcile(subUnit); 1049 final IJavaProject project= subUnit.getJavaProject(); 1050 final ASTParser parser= ASTParser.newParser(AST.JLS3); 1051 parser.setWorkingCopyOwner(fOwner); 1052 parser.setResolveBindings(true); 1053 parser.setProject(project); 1054 parser.setCompilerOptions(RefactoringASTParser.getCompilerOptions(project)); 1055 parser.createASTs(new ICompilationUnit[] { subUnit}, new String [0], new ASTRequestor() { 1056 1057 public final void acceptAST(final ICompilationUnit unit, final CompilationUnit node) { 1058 try { 1059 final IType subType= (IType) JavaModelUtil.findInCompilationUnit(unit, fSubType); 1060 final AbstractTypeDeclaration subDeclaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(subType, node); 1061 if (subDeclaration != null) { 1062 final ITypeBinding subBinding= subDeclaration.resolveBinding(); 1063 if (subBinding != null) { 1064 String name= null; 1065 ITypeBinding superBinding= null; 1066 final ITypeBinding[] superBindings= subBinding.getInterfaces(); 1067 for (int index= 0; index < superBindings.length; index++) { 1068 name= superBindings[index].getName(); 1069 if (name.startsWith(fSuperName) && superBindings[index].getTypeArguments().length == subBinding.getTypeParameters().length) 1070 superBinding= superBindings[index]; 1071 } 1072 if (superBinding != null) { 1073 solveSuperTypeConstraints(unit, node, subType, subBinding, superBinding, new SubProgressMonitor(monitor, 80), status); 1074 if (!status.hasFatalError()) { 1075 rewriteTypeOccurrences(manager, this, sourceRewrite, unit, node, replacements, status, new SubProgressMonitor(monitor, 200)); 1076 if (manager.containsChangesIn(superUnit)) { 1077 final TextEditBasedChange change= manager.get(superUnit); 1078 if (change instanceof TextChange) { 1079 final TextEdit edit= ((TextChange) change).getEdit(); 1080 if (edit != null) { 1081 final IDocument document= new Document(superUnit.getBuffer().getContents()); 1082 try { 1083 edit.apply(document, TextEdit.UPDATE_REGIONS); 1084 } catch (MalformedTreeException exception) { 1085 JavaPlugin.log(exception); 1086 status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_internal_error)); 1087 } catch (BadLocationException exception) { 1088 JavaPlugin.log(exception); 1089 status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_internal_error)); 1090 } 1091 fSuperSource= document.get(); 1092 manager.remove(superUnit); 1093 } 1094 } 1095 } 1096 } 1097 } 1098 } 1099 } 1100 } catch (JavaModelException exception) { 1101 JavaPlugin.log(exception); 1102 status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_internal_error)); 1103 } 1104 } 1105 1106 public final void acceptBinding(final String key, final IBinding binding) { 1107 } 1109 }, new NullProgressMonitor()); 1110 } finally { 1111 monitor.done(); 1112 } 1113 } 1114 1115 1122 public final void setAbstract(final boolean declare) { 1123 fAbstract= declare; 1124 } 1125 1126 1133 public final void setComments(final boolean comments) { 1134 fComments= comments; 1135 } 1136 1137 1145 public final void setExtractedMembers(final IMember[] members) throws JavaModelException { 1146 fMembers= members; 1147 } 1148 1149 1156 public final void setPublic(final boolean declare) { 1157 fPublic= declare; 1158 } 1159 1160 1166 public final void setTypeName(final String name) { 1167 Assert.isNotNull(name); 1168 fSuperName= name; 1169 } 1170} 1171 | Popular Tags |