| /******************************************************************************* |
| * Copyright (c) 2000, 2016 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Jerome Cambon <jerome.cambon@oracle.com> - [code style] don't generate redundant modifiers "public static final abstract" for interface members - https://bugs.eclipse.org/71627 |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.corext.refactoring.structure; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Comparator; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.core.runtime.OperationCanceledException; |
| import org.eclipse.core.runtime.SubProgressMonitor; |
| |
| import org.eclipse.core.resources.IFile; |
| |
| import org.eclipse.core.filebuffers.ITextFileBuffer; |
| |
| import org.eclipse.text.edits.MalformedTreeException; |
| import org.eclipse.text.edits.TextEdit; |
| |
| import org.eclipse.jface.text.BadLocationException; |
| import org.eclipse.jface.text.Document; |
| import org.eclipse.jface.text.IDocument; |
| |
| import org.eclipse.ltk.core.refactoring.Change; |
| import org.eclipse.ltk.core.refactoring.GroupCategory; |
| import org.eclipse.ltk.core.refactoring.GroupCategorySet; |
| import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; |
| import org.eclipse.ltk.core.refactoring.RefactoringStatus; |
| import org.eclipse.ltk.core.refactoring.TextChange; |
| import org.eclipse.ltk.core.refactoring.TextEditBasedChange; |
| import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; |
| import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant; |
| import org.eclipse.ltk.core.refactoring.participants.SharableParticipants; |
| |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.IField; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IMember; |
| import org.eclipse.jdt.core.IMethod; |
| import org.eclipse.jdt.core.IPackageFragment; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.ITypeParameter; |
| import org.eclipse.jdt.core.JavaCore; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.core.dom.AST; |
| import org.eclipse.jdt.core.dom.ASTNode; |
| import org.eclipse.jdt.core.dom.ASTParser; |
| import org.eclipse.jdt.core.dom.ASTRequestor; |
| import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; |
| import org.eclipse.jdt.core.dom.Annotation; |
| import org.eclipse.jdt.core.dom.CompilationUnit; |
| import org.eclipse.jdt.core.dom.EnumDeclaration; |
| import org.eclipse.jdt.core.dom.FieldDeclaration; |
| import org.eclipse.jdt.core.dom.IBinding; |
| import org.eclipse.jdt.core.dom.IExtendedModifier; |
| import org.eclipse.jdt.core.dom.IMethodBinding; |
| import org.eclipse.jdt.core.dom.ITypeBinding; |
| import org.eclipse.jdt.core.dom.IVariableBinding; |
| import org.eclipse.jdt.core.dom.MethodDeclaration; |
| import org.eclipse.jdt.core.dom.Modifier; |
| import org.eclipse.jdt.core.dom.NodeFinder; |
| import org.eclipse.jdt.core.dom.ParameterizedType; |
| import org.eclipse.jdt.core.dom.SingleVariableDeclaration; |
| import org.eclipse.jdt.core.dom.Type; |
| import org.eclipse.jdt.core.dom.TypeDeclaration; |
| import org.eclipse.jdt.core.dom.VariableDeclarationFragment; |
| import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; |
| import org.eclipse.jdt.core.dom.rewrite.ITrackedNodePosition; |
| import org.eclipse.jdt.core.dom.rewrite.ListRewrite; |
| import org.eclipse.jdt.core.refactoring.IJavaRefactorings; |
| import org.eclipse.jdt.core.refactoring.descriptors.ExtractInterfaceDescriptor; |
| import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor; |
| |
| import org.eclipse.jdt.internal.core.refactoring.descriptors.RefactoringSignatureDescriptorFactory; |
| import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings; |
| import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility; |
| import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility2; |
| import org.eclipse.jdt.internal.corext.dom.Bindings; |
| import org.eclipse.jdt.internal.corext.dom.ModifierRewrite; |
| import org.eclipse.jdt.internal.corext.refactoring.Checks; |
| import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment; |
| import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments; |
| import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil; |
| import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; |
| import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext; |
| import org.eclipse.jdt.internal.corext.refactoring.changes.CreateCompilationUnitChange; |
| import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange; |
| import org.eclipse.jdt.internal.corext.refactoring.reorg.ASTNodeDeleteUtil; |
| import org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeConstraintsModel; |
| import org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeConstraintsSolver; |
| import org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeRefactoringProcessor; |
| import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.CompilationUnitRange; |
| import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType; |
| import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ISourceConstraintVariable; |
| import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeConstraintVariable; |
| import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser; |
| import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringFileBuffers; |
| import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil; |
| import org.eclipse.jdt.internal.corext.refactoring.util.TextEditBasedChangeManager; |
| import org.eclipse.jdt.internal.corext.util.JavaModelUtil; |
| import org.eclipse.jdt.internal.corext.util.JdtFlags; |
| import org.eclipse.jdt.internal.corext.util.Messages; |
| import org.eclipse.jdt.internal.corext.util.Strings; |
| |
| import org.eclipse.jdt.ui.CodeGeneration; |
| import org.eclipse.jdt.ui.JavaElementLabels; |
| |
| import org.eclipse.jdt.internal.ui.JavaPlugin; |
| import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider; |
| import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings; |
| import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels; |
| |
| |
| /** |
| * Refactoring processor to extract interfaces. |
| */ |
| public final class ExtractInterfaceProcessor extends SuperTypeRefactoringProcessor { |
| |
| private static final String ATTRIBUTE_COMMENTS= "comments"; //$NON-NLS-1$ |
| |
| /** The identifier of this processor */ |
| public static final String IDENTIFIER= "org.eclipse.jdt.ui.extractInterfaceProcessor"; //$NON-NLS-1$ |
| |
| /** The extract interface group category set */ |
| private static final GroupCategorySet SET_EXTRACT_INTERFACE= new GroupCategorySet(new GroupCategory("org.eclipse.jdt.internal.corext.extractInterface", //$NON-NLS-1$ |
| RefactoringCoreMessages.ExtractInterfaceProcessor_category_name, RefactoringCoreMessages.ExtractInterfaceProcessor_category_description)); |
| |
| /** |
| * Is the specified member extractable from the type? |
| * |
| * @param member |
| * the member to test |
| * @return <code>true</code> if the member is extractable, |
| * <code>false</code> otherwise |
| * @throws JavaModelException |
| * if an error occurs |
| */ |
| protected static boolean isExtractableMember(final IMember member) throws JavaModelException { |
| Assert.isNotNull(member); |
| switch (member.getElementType()) { |
| case IJavaElement.METHOD: |
| return JdtFlags.isPublic(member) && !JdtFlags.isStatic(member) && !((IMethod) member).isConstructor(); |
| case IJavaElement.FIELD: |
| return JdtFlags.isPublic(member) && JdtFlags.isStatic(member) && JdtFlags.isFinal(member) && !JdtFlags.isEnum(member); |
| default: |
| return false; |
| } |
| } |
| |
| /** Should override annotations be generated? */ |
| private boolean fAnnotations= false; |
| |
| /** The text edit based change manager */ |
| private TextEditBasedChangeManager fChangeManager= null; |
| |
| /** Should comments be generated? */ |
| private boolean fComments= true; |
| |
| /** The members to extract */ |
| private IMember[] fMembers= null; |
| |
| /** The subtype where to extract the supertype */ |
| private IType fSubType; |
| |
| /** The supertype name */ |
| private String fSuperName; |
| |
| /** The source of the new supertype */ |
| private String fSuperSource= null; |
| |
| /** |
| * Creates a new extract interface processor. |
| * |
| * @param type |
| * the type where to extract the supertype, or <code>null</code> |
| * if invoked by scripting |
| * @param settings |
| * the code generation settings, or <code>null</code> if |
| * invoked by scripting |
| */ |
| public ExtractInterfaceProcessor(final IType type, final CodeGenerationSettings settings) { |
| super(settings); |
| fSubType= type; |
| if (fSubType != null) |
| fSuperName= fSubType.getElementName(); |
| } |
| |
| /** |
| * Creates a new extract interface processor from refactoring arguments. |
| * |
| * @param arguments |
| * the refactoring arguments |
| * @param status |
| * the resulting status |
| */ |
| public ExtractInterfaceProcessor(JavaRefactoringArguments arguments, RefactoringStatus status) { |
| super(null); |
| RefactoringStatus initializeStatus= initialize(arguments); |
| status.merge(initializeStatus); |
| } |
| |
| /* |
| * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#checkFinalConditions(org.eclipse.core.runtime.IProgressMonitor,org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext) |
| */ |
| @Override |
| public final RefactoringStatus checkFinalConditions(final IProgressMonitor monitor, final CheckConditionsContext context) throws CoreException, OperationCanceledException { |
| Assert.isNotNull(monitor); |
| Assert.isNotNull(context); |
| final RefactoringStatus status= new RefactoringStatus(); |
| fChangeManager= new TextEditBasedChangeManager(); |
| try { |
| monitor.beginTask("", 1); //$NON-NLS-1$ |
| monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_checking); |
| status.merge(Checks.checkIfCuBroken(fSubType)); |
| if (!status.hasError()) { |
| if (fSubType.isBinary() || fSubType.isReadOnly() || !fSubType.exists()) |
| status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_no_binary, JavaStatusContext.create(fSubType))); |
| else if (fSubType.isAnonymous()) |
| status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_no_anonymous, JavaStatusContext.create(fSubType))); |
| else if (fSubType.isAnnotation()) |
| status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_no_annotation, JavaStatusContext.create(fSubType))); |
| else { |
| status.merge(checkSuperType()); |
| if (!status.hasFatalError()) { |
| if (!status.hasFatalError()) { |
| fChangeManager= createChangeManager(new SubProgressMonitor(monitor, 1), status); |
| if (!status.hasFatalError()) { |
| Checks.addModifiedFilesToChecker(ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits()), context); |
| } |
| } |
| } |
| } |
| } |
| } finally { |
| monitor.done(); |
| } |
| return status; |
| } |
| |
| /* |
| * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#checkInitialConditions(org.eclipse.core.runtime.IProgressMonitor) |
| */ |
| @Override |
| public final RefactoringStatus checkInitialConditions(final IProgressMonitor monitor) throws CoreException, OperationCanceledException { |
| Assert.isNotNull(monitor); |
| final RefactoringStatus status= new RefactoringStatus(); |
| try { |
| monitor.beginTask("", 1); //$NON-NLS-1$ |
| monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_checking); |
| status.merge(Checks.checkIfCuBroken(fSubType)); |
| monitor.worked(1); |
| } finally { |
| monitor.done(); |
| } |
| return status; |
| } |
| |
| /** |
| * Checks whether the supertype clashes with existing types. |
| * |
| * @return the status of the condition checking |
| * @throws JavaModelException |
| * if an error occurs |
| */ |
| protected final RefactoringStatus checkSuperType() throws JavaModelException { |
| final IPackageFragment fragment= fSubType.getPackageFragment(); |
| final IType type= Checks.findTypeInPackage(fragment, fSuperName); |
| if (type != null && type.exists()) { |
| if (fragment.isDefaultPackage()) |
| return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.ExtractInterfaceProcessor_existing_default_type, BasicElementLabels.getJavaElementName(fSuperName))); |
| else { |
| String packageLabel= JavaElementLabels.getElementLabel(fragment, JavaElementLabels.ALL_DEFAULT); |
| return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.ExtractInterfaceProcessor_existing_type, new String[] { BasicElementLabels.getJavaElementName(fSuperName), packageLabel })); |
| } |
| } |
| return new RefactoringStatus(); |
| } |
| |
| /** |
| * Checks whether the type name is valid. |
| * |
| * @param name |
| * the name to check |
| * @return the status of the condition checking |
| */ |
| public final RefactoringStatus checkTypeName(final String name) { |
| Assert.isNotNull(name); |
| try { |
| final RefactoringStatus result= Checks.checkTypeName(name, fSubType); |
| if (result.hasFatalError()) |
| return result; |
| final String unitName= JavaModelUtil.getRenamedCUName(fSubType.getCompilationUnit(), name); |
| result.merge(Checks.checkCompilationUnitName(unitName, fSubType)); |
| if (result.hasFatalError()) |
| return result; |
| final IPackageFragment fragment= fSubType.getPackageFragment(); |
| if (fragment.getCompilationUnit(unitName).exists()) { |
| result.addFatalError(Messages.format(RefactoringCoreMessages.ExtractInterfaceProcessor_existing_compilation_unit, new String[] { BasicElementLabels.getResourceName(unitName), JavaElementLabels.getElementLabel(fragment, JavaElementLabels.ALL_DEFAULT) })); |
| return result; |
| } |
| result.merge(checkSuperType()); |
| return result; |
| } catch (JavaModelException exception) { |
| return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_internal_error); |
| } |
| } |
| |
| /* |
| * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#createChange(org.eclipse.core.runtime.IProgressMonitor) |
| */ |
| @Override |
| public final Change createChange(final IProgressMonitor monitor) throws CoreException, OperationCanceledException { |
| Assert.isNotNull(monitor); |
| try { |
| monitor.beginTask("", 1); //$NON-NLS-1$ |
| monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating); |
| final Map<String, String> arguments= new HashMap<>(); |
| String project= null; |
| final IJavaProject javaProject= fSubType.getJavaProject(); |
| if (javaProject != null) |
| project= javaProject.getElementName(); |
| int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE | RefactoringDescriptor.MULTI_CHANGE; |
| try { |
| if (fSubType.isLocal() || fSubType.isAnonymous()) |
| flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT; |
| } catch (JavaModelException exception) { |
| JavaPlugin.log(exception); |
| } |
| final IPackageFragment fragment= fSubType.getPackageFragment(); |
| final ICompilationUnit cu= fragment.getCompilationUnit(JavaModelUtil.getRenamedCUName(fSubType.getCompilationUnit(), fSuperName)); |
| final IType type= cu.getType(fSuperName); |
| final String description= Messages.format(RefactoringCoreMessages.ExtractInterfaceProcessor_description_descriptor_short, BasicElementLabels.getJavaElementName(fSuperName)); |
| 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) }); |
| final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header); |
| comment.addSetting(Messages.format(RefactoringCoreMessages.ExtractInterfaceProcessor_refactored_element_pattern, JavaElementLabels.getElementLabel(type, JavaElementLabels.ALL_FULLY_QUALIFIED))); |
| final String[] settings= new String[fMembers.length]; |
| for (int index= 0; index < settings.length; index++) |
| settings[index]= JavaElementLabels.getElementLabel(fMembers[index], JavaElementLabels.ALL_FULLY_QUALIFIED); |
| comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ExtractInterfaceProcessor_extracted_members_pattern, settings)); |
| addSuperTypeSettings(comment, true); |
| final ExtractInterfaceDescriptor descriptor= RefactoringSignatureDescriptorFactory.createExtractInterfaceDescriptor(project, description, comment.asString(), arguments, flags); |
| arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT, JavaRefactoringDescriptorUtil.elementToHandle(project, fSubType)); |
| arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME, fSuperName); |
| for (int index= 0; index < fMembers.length; index++) |
| arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + (index + 1), JavaRefactoringDescriptorUtil.elementToHandle(project, fMembers[index])); |
| arguments.put(ATTRIBUTE_COMMENTS, Boolean.valueOf(fComments).toString()); |
| arguments.put(ATTRIBUTE_REPLACE, Boolean.valueOf(fReplace).toString()); |
| arguments.put(ATTRIBUTE_INSTANCEOF, Boolean.valueOf(fInstanceOf).toString()); |
| final DynamicValidationRefactoringChange change= new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.ExtractInterfaceRefactoring_name, fChangeManager.getAllChanges()); |
| final IFile file= ResourceUtil.getFile(fSubType.getCompilationUnit()); |
| if (fSuperSource != null && fSuperSource.length() > 0) |
| change.add(new CreateCompilationUnitChange(fSubType.getPackageFragment().getCompilationUnit(JavaModelUtil.getRenamedCUName(fSubType.getCompilationUnit(), fSuperName)), fSuperSource, file.getCharset(false))); |
| monitor.worked(1); |
| return change; |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Creates the text change manager for this processor. |
| * |
| * @param monitor |
| * the progress monitor to display progress |
| * @param status |
| * the refactoring status |
| * @return the created text change manager |
| * @throws JavaModelException |
| * if the method declaration could not be found |
| * @throws CoreException |
| * if the changes could not be generated |
| */ |
| protected final TextEditBasedChangeManager createChangeManager(final IProgressMonitor monitor, final RefactoringStatus status) throws JavaModelException, CoreException { |
| Assert.isNotNull(status); |
| Assert.isNotNull(monitor); |
| try { |
| monitor.beginTask("", 300); //$NON-NLS-1$ |
| monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating); |
| resetEnvironment(); |
| final TextEditBasedChangeManager manager= new TextEditBasedChangeManager(); |
| final CompilationUnitRewrite sourceRewrite= new CompilationUnitRewrite(fSubType.getCompilationUnit()); |
| final AbstractTypeDeclaration declaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(fSubType, sourceRewrite.getRoot()); |
| if (declaration != null) { |
| createTypeSignature(sourceRewrite, declaration, status, new SubProgressMonitor(monitor, 20)); |
| final IField[] fields= getExtractedFields(fSubType.getCompilationUnit()); |
| if (fields.length > 0) |
| ASTNodeDeleteUtil.markAsDeleted(fields, sourceRewrite, sourceRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.ExtractInterfaceProcessor_remove_field_label, SET_EXTRACT_INTERFACE)); |
| if (fSubType.isInterface()) { |
| final IMethod[] methods= getExtractedMethods(fSubType.getCompilationUnit()); |
| if (methods.length > 0) |
| ASTNodeDeleteUtil.markAsDeleted(methods, sourceRewrite, sourceRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.ExtractInterfaceProcessor_remove_method_label, SET_EXTRACT_INTERFACE)); |
| } |
| final String name= JavaModelUtil.getRenamedCUName(fSubType.getCompilationUnit(), fSuperName); |
| final ICompilationUnit original= fSubType.getPackageFragment().getCompilationUnit(name); |
| final ICompilationUnit copy= getSharedWorkingCopy(original.getPrimary(), new SubProgressMonitor(monitor, 20)); |
| fSuperSource= createTypeSource(copy, fSubType, fSuperName, sourceRewrite, declaration, status, new SubProgressMonitor(monitor, 40)); |
| if (fSuperSource != null) { |
| copy.getBuffer().setContents(fSuperSource); |
| JavaModelUtil.reconcile(copy); |
| } |
| final Set<String> replacements= new HashSet<>(); |
| if (fReplace) |
| rewriteTypeOccurrences(manager, sourceRewrite, copy, replacements, status, new SubProgressMonitor(monitor, 220)); |
| rewriteSourceMethods(sourceRewrite, replacements); |
| manager.manage(fSubType.getCompilationUnit(), sourceRewrite.createChange(true)); |
| } |
| return manager; |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /* |
| * @see org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeRefactoringProcessor#createContraintSolver(org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeConstraintsModel) |
| */ |
| @Override |
| protected final SuperTypeConstraintsSolver createContraintSolver(final SuperTypeConstraintsModel model) { |
| return new ExtractInterfaceConstraintsSolver(model, fSuperName); |
| } |
| |
| /** |
| * Creates a target field declaration. |
| * |
| * @param sourceRewrite |
| * the source compilation unit rewrite |
| * @param targetRewrite |
| * the target rewrite |
| * @param targetDeclaration |
| * the target type declaration |
| * @param fragment |
| * the source variable declaration fragment |
| * @throws CoreException |
| * if a buffer could not be retrieved |
| */ |
| protected final void createFieldDeclaration(final CompilationUnitRewrite sourceRewrite, final ASTRewrite targetRewrite, final AbstractTypeDeclaration targetDeclaration, final VariableDeclarationFragment fragment) throws CoreException { |
| Assert.isNotNull(targetDeclaration); |
| Assert.isNotNull(sourceRewrite); |
| Assert.isNotNull(targetRewrite); |
| Assert.isNotNull(fragment); |
| final FieldDeclaration field= (FieldDeclaration) fragment.getParent(); |
| ImportRewriteUtil.collectImports(fSubType.getJavaProject(), field, fTypeBindings, fStaticBindings, false); |
| final ASTRewrite rewrite= ASTRewrite.create(field.getAST()); |
| final ITrackedNodePosition position= rewrite.track(field); |
| final ListRewrite rewriter= rewrite.getListRewrite(field, FieldDeclaration.FRAGMENTS_PROPERTY); |
| VariableDeclarationFragment current= null; |
| for (final Iterator<VariableDeclarationFragment> iterator= field.fragments().iterator(); iterator.hasNext();) { |
| current= iterator.next(); |
| if (!current.getName().getIdentifier().equals(fragment.getName().getIdentifier())) |
| rewriter.remove(current, null); |
| } |
| int modifiers= field.getModifiers(); |
| modifiers= JdtFlags.clearAccessModifiers(modifiers); |
| modifiers= JdtFlags.clearFlag(Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL, modifiers); |
| ModifierRewrite.create(rewrite, field).setModifiers(modifiers, null); |
| final ICompilationUnit unit= sourceRewrite.getCu(); |
| final ITextFileBuffer buffer= RefactoringFileBuffers.acquire(unit); |
| try { |
| final IDocument document= new Document(buffer.getDocument().get()); |
| try { |
| rewrite.rewriteAST(document, unit.getJavaProject().getOptions(true)).apply(document, TextEdit.UPDATE_REGIONS); |
| targetRewrite.getListRewrite(targetDeclaration, targetDeclaration.getBodyDeclarationsProperty()).insertFirst(targetRewrite.createStringPlaceholder(normalizeText(document.get(position.getStartPosition(), position.getLength())), ASTNode.FIELD_DECLARATION), null); |
| } catch (MalformedTreeException exception) { |
| JavaPlugin.log(exception); |
| } catch (BadLocationException exception) { |
| JavaPlugin.log(exception); |
| } |
| } finally { |
| RefactoringFileBuffers.release(unit); |
| } |
| } |
| |
| @Override |
| protected final void createMemberDeclarations(final CompilationUnitRewrite sourceRewrite, final ASTRewrite targetRewrite, final AbstractTypeDeclaration targetDeclaration) throws CoreException { |
| Assert.isNotNull(sourceRewrite); |
| Assert.isNotNull(targetRewrite); |
| Assert.isNotNull(targetDeclaration); |
| Arrays.sort(fMembers, new Comparator<IMember>() { |
| |
| @Override |
| public final int compare(final IMember first, final IMember second) { |
| try { |
| return first.getSourceRange().getOffset() - second.getSourceRange().getOffset(); |
| } catch (JavaModelException exception) { |
| return first.hashCode() - second.hashCode(); |
| } |
| } |
| }); |
| fTypeBindings.clear(); |
| fStaticBindings.clear(); |
| if (fMembers.length > 0) { |
| IMember member= null; |
| for (int index= fMembers.length - 1; index >= 0; index--) { |
| member= fMembers[index]; |
| if (member instanceof IField) { |
| createFieldDeclaration(sourceRewrite, targetRewrite, targetDeclaration, ASTNodeSearchUtil.getFieldDeclarationFragmentNode((IField) member, sourceRewrite.getRoot())); |
| } else if (member instanceof IMethod) { |
| createMethodDeclaration(sourceRewrite, targetRewrite, targetDeclaration, ASTNodeSearchUtil.getMethodDeclarationNode((IMethod) member, sourceRewrite.getRoot())); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Creates the method comment for the specified declaration. |
| * |
| * @param sourceRewrite |
| * the compilation unit rewrite |
| * @param declaration |
| * the method declaration |
| * @param replacements |
| * the set of variable binding keys of formal parameters which |
| * must be replaced |
| * @param javadoc |
| * <code>true</code> if javadoc comments are processed, |
| * <code>false</code> otherwise |
| * @throws CoreException |
| * if an error occurs |
| */ |
| protected final void createMethodComment(final CompilationUnitRewrite sourceRewrite, final MethodDeclaration declaration, final Set<String> replacements, final boolean javadoc) throws CoreException { |
| Assert.isNotNull(sourceRewrite); |
| Assert.isNotNull(declaration); |
| Assert.isNotNull(replacements); |
| final IMethodBinding binding= declaration.resolveBinding(); |
| if (binding != null) { |
| IVariableBinding variable= null; |
| SingleVariableDeclaration argument= null; |
| final IPackageFragment fragment= fSubType.getPackageFragment(); |
| final String string= fragment.isDefaultPackage() ? fSuperName : fragment.getElementName() + "." + fSuperName; //$NON-NLS-1$ |
| final ITypeBinding[] bindings= binding.getParameterTypes(); |
| final String[] names= new String[bindings.length]; |
| for (int offset= 0; offset < names.length; offset++) { |
| argument= (SingleVariableDeclaration) declaration.parameters().get(offset); |
| variable= argument.resolveBinding(); |
| if (variable != null) { |
| if (replacements.contains(variable.getKey())) |
| names[offset]= string; |
| else { |
| if (binding.isVarargs() && bindings[offset].isArray() && offset == names.length - 1) |
| names[offset]= Bindings.getFullyQualifiedName(bindings[offset].getElementType()); |
| else |
| names[offset]= Bindings.getFullyQualifiedName(bindings[offset]); |
| } |
| } |
| } |
| final String comment= CodeGeneration.getMethodComment(fSubType.getCompilationUnit(), fSubType.getElementName(), declaration, false, binding.getName(), string, names, StubUtility.getLineDelimiterUsed(fSubType.getJavaProject())); |
| if (comment != null) { |
| final ASTRewrite rewrite= sourceRewrite.getASTRewrite(); |
| if (declaration.getJavadoc() != null) { |
| rewrite.replace(declaration.getJavadoc(), rewrite.createStringPlaceholder(comment, ASTNode.JAVADOC), sourceRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.ExtractInterfaceProcessor_rewrite_comment, SET_EXTRACT_INTERFACE)); |
| } else if (javadoc) { |
| rewrite.set(declaration, MethodDeclaration.JAVADOC_PROPERTY, rewrite.createStringPlaceholder(comment, ASTNode.JAVADOC), sourceRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.ExtractInterfaceProcessor_add_comment, SET_EXTRACT_INTERFACE)); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Rewrites the extracted methods in the source type. |
| * Adds/removes method annotations and adds method comments. |
| * |
| * @param sourceRewrite |
| * the source compilation unit rewrite |
| * @param replacements |
| * the set of variable binding keys of formal parameters which |
| * must be replaced |
| * @throws CoreException |
| * if an error occurs |
| */ |
| private void rewriteSourceMethods(final CompilationUnitRewrite sourceRewrite, final Set<String> replacements) throws CoreException { |
| Assert.isNotNull(sourceRewrite); |
| Assert.isNotNull(replacements); |
| if (fMembers.length > 0) { |
| IJavaProject project= fSubType.getJavaProject(); |
| boolean annotations= fAnnotations && !JavaModelUtil.isVersionLessThan(project.getOption(JavaCore.COMPILER_SOURCE, true), JavaCore.VERSION_1_6); |
| boolean inheritNullAnnotations= JavaCore.ENABLED.equals(project.getOption(JavaCore.COMPILER_INHERIT_NULL_ANNOTATIONS, true)); |
| boolean javadoc= project.getOption(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, true).equals(JavaCore.ENABLED); |
| IMember member= null; |
| for (int index= 0; index < fMembers.length; index++) { |
| member= fMembers[index]; |
| if (member instanceof IMethod) { |
| MethodDeclaration declaration= ASTNodeSearchUtil.getMethodDeclarationNode((IMethod) member, sourceRewrite.getRoot()); |
| if (inheritNullAnnotations) { |
| for (IExtendedModifier extended : (List<IExtendedModifier>) declaration.modifiers()) { |
| if (extended.isAnnotation()) { |
| Annotation annotation= (Annotation) extended; |
| ITypeBinding binding= annotation.resolveTypeBinding(); |
| if (binding != null && Bindings.isAnyNullAnnotation(binding, project)) { |
| ASTRewrite rewrite= sourceRewrite.getASTRewrite(); |
| rewrite.getListRewrite(declaration, MethodDeclaration.MODIFIERS2_PROPERTY).remove(annotation, null); |
| } |
| } |
| } |
| for (SingleVariableDeclaration parameter : (List<SingleVariableDeclaration>) declaration.parameters()) { |
| for (IExtendedModifier extended : (List<IExtendedModifier>) parameter.modifiers()) { |
| if (extended.isAnnotation()) { |
| Annotation annotation= (Annotation) extended; |
| ITypeBinding binding= annotation.resolveTypeBinding(); |
| if (binding != null && Bindings.isAnyNullAnnotation(binding, project)) { |
| ASTRewrite rewrite= sourceRewrite.getASTRewrite(); |
| rewrite.getListRewrite(parameter, SingleVariableDeclaration.MODIFIERS2_PROPERTY).remove(annotation, null); |
| } |
| } |
| } |
| } |
| } |
| if (annotations) { |
| StubUtility2.createOverrideAnnotation(sourceRewrite.getASTRewrite(), sourceRewrite.getImportRewrite(), declaration, null); |
| } |
| if (fComments) |
| createMethodComment(sourceRewrite, declaration, replacements, javadoc); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Creates a target method declaration. |
| * |
| * @param sourceRewrite |
| * the source compilation unit rewrite |
| * @param targetRewrite |
| * the target rewrite |
| * @param targetDeclaration |
| * the target type declaration |
| * @param declaration |
| * the source method declaration |
| * @throws CoreException |
| * if a buffer could not be retrieved |
| */ |
| protected final void createMethodDeclaration(final CompilationUnitRewrite sourceRewrite, final ASTRewrite targetRewrite, final AbstractTypeDeclaration targetDeclaration, final MethodDeclaration declaration) throws CoreException { |
| Assert.isNotNull(targetDeclaration); |
| Assert.isNotNull(sourceRewrite); |
| Assert.isNotNull(targetRewrite); |
| Assert.isNotNull(declaration); |
| IJavaProject sourceProject= fSubType.getJavaProject(); |
| ImportRewriteUtil.collectImports(sourceProject, declaration, fTypeBindings, fStaticBindings, true); |
| ASTRewrite rewrite= ASTRewrite.create(declaration.getAST()); |
| ITrackedNodePosition position= rewrite.track(declaration); |
| if (declaration.getBody() != null) |
| rewrite.remove(declaration.getBody(), null); |
| ListRewrite list= rewrite.getListRewrite(declaration, declaration.getModifiersProperty()); |
| Annotation annotation= null; |
| for (IExtendedModifier extended : (List<IExtendedModifier>) declaration.modifiers()) { |
| if (!extended.isAnnotation()) { |
| Modifier modifier= (Modifier) extended; |
| list.remove(modifier, null); |
| } else if (extended.isAnnotation()) { |
| annotation= (Annotation) extended; |
| ITypeBinding binding= annotation.resolveTypeBinding(); |
| if (binding != null && binding.getQualifiedName().equals("java.lang.Override") || ! Bindings.isAnyNullAnnotation(binding, sourceProject)) //$NON-NLS-1$ |
| list.remove(annotation, null); |
| } |
| } |
| |
| for (SingleVariableDeclaration param : (List<SingleVariableDeclaration>) declaration.parameters()) { |
| ListRewrite modifierRewrite= rewrite.getListRewrite(param, SingleVariableDeclaration.MODIFIERS2_PROPERTY); |
| for (IExtendedModifier extended : (List<IExtendedModifier>) param.modifiers()) { |
| if (!extended.isAnnotation()) { |
| Modifier modifier= (Modifier) extended; |
| modifierRewrite.remove(modifier, null); |
| } else if (extended.isAnnotation()) { |
| annotation= (Annotation) extended; |
| ITypeBinding binding= annotation.resolveTypeBinding(); |
| if (binding != null && ! Bindings.isAnyNullAnnotation(binding, sourceProject)) |
| modifierRewrite.remove(annotation, null); |
| } |
| } |
| } |
| |
| ICompilationUnit unit= sourceRewrite.getCu(); |
| ITextFileBuffer buffer= RefactoringFileBuffers.acquire(unit); |
| try { |
| IDocument document= new Document(buffer.getDocument().get()); |
| try { |
| rewrite.rewriteAST(document, unit.getJavaProject().getOptions(true)).apply(document, TextEdit.UPDATE_REGIONS); |
| targetRewrite.getListRewrite(targetDeclaration, targetDeclaration.getBodyDeclarationsProperty()).insertFirst(targetRewrite.createStringPlaceholder(normalizeText(document.get(position.getStartPosition(), position.getLength())), ASTNode.METHOD_DECLARATION), null); |
| } catch (MalformedTreeException exception) { |
| JavaPlugin.log(exception); |
| } catch (BadLocationException exception) { |
| JavaPlugin.log(exception); |
| } |
| } finally { |
| RefactoringFileBuffers.release(unit); |
| } |
| } |
| |
| /** |
| * Creates the new signature of the source type. |
| * |
| * @param rewrite |
| * the source compilation unit rewrite |
| * @param declaration |
| * the type declaration |
| * @param status |
| * the refactoring status |
| * @param monitor |
| * the progress monitor to use |
| * @throws JavaModelException |
| * if the type parameters cannot be retrieved |
| */ |
| protected final void createTypeSignature(final CompilationUnitRewrite rewrite, final AbstractTypeDeclaration declaration, final RefactoringStatus status, final IProgressMonitor monitor) throws JavaModelException { |
| Assert.isNotNull(rewrite); |
| Assert.isNotNull(declaration); |
| Assert.isNotNull(status); |
| Assert.isNotNull(monitor); |
| try { |
| monitor.beginTask("", 1); //$NON-NLS-1$ |
| monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating); |
| final AST ast= declaration.getAST(); |
| final ITypeParameter[] parameters= fSubType.getTypeParameters(); |
| Type type= ast.newSimpleType(ast.newSimpleName(fSuperName)); |
| if (parameters.length > 0) { |
| final ParameterizedType parameterized= ast.newParameterizedType(type); |
| for (int index= 0; index < parameters.length; index++) |
| parameterized.typeArguments().add(ast.newSimpleType(ast.newSimpleName(parameters[index].getElementName()))); |
| type= parameterized; |
| } |
| final ASTRewrite rewriter= rewrite.getASTRewrite(); |
| if (declaration instanceof TypeDeclaration) |
| rewriter.getListRewrite(declaration, TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY).insertLast(type, rewrite.createCategorizedGroupDescription(RefactoringCoreMessages.ExtractInterfaceProcessor_add_super_interface, SET_EXTRACT_INTERFACE)); |
| else if (declaration instanceof EnumDeclaration) |
| rewriter.getListRewrite(declaration, EnumDeclaration.SUPER_INTERFACE_TYPES_PROPERTY).insertLast(type, rewrite.createCategorizedGroupDescription(RefactoringCoreMessages.ExtractInterfaceProcessor_add_super_interface, SET_EXTRACT_INTERFACE)); |
| monitor.worked(1); |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /* |
| * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#getElements() |
| */ |
| @Override |
| public final Object[] getElements() { |
| return new Object[] { fSubType }; |
| } |
| |
| /** |
| * Returns the list of extractable members from the type. |
| * |
| * @return the list of extractable members |
| * @throws JavaModelException |
| * if an error occurs |
| */ |
| public final IMember[] getExtractableMembers() throws JavaModelException { |
| final List<IJavaElement> list= new ArrayList<>(); |
| IJavaElement[] children= fSubType.getChildren(); |
| for (int index= 0; index < children.length; index++) { |
| if (children[index] instanceof IMember && isExtractableMember((IMember) children[index])) |
| list.add(children[index]); |
| } |
| final IMember[] members= new IMember[list.size()]; |
| list.toArray(members); |
| return members; |
| } |
| |
| /** |
| * Returns the extracted fields from the compilation unit. |
| * |
| * @param unit |
| * the compilation unit |
| * @return the extracted fields |
| */ |
| protected final IField[] getExtractedFields(final ICompilationUnit unit) { |
| Assert.isNotNull(unit); |
| final List<IJavaElement> list= new ArrayList<>(); |
| for (int index= 0; index < fMembers.length; index++) { |
| if (fMembers[index] instanceof IField) { |
| final IJavaElement element= JavaModelUtil.findInCompilationUnit(unit, fMembers[index]); |
| if (element instanceof IField) |
| list.add(element); |
| } |
| } |
| final IField[] fields= new IField[list.size()]; |
| list.toArray(fields); |
| return fields; |
| } |
| |
| /** |
| * Returns the extracted methods from the compilation unit except the default methods. |
| * |
| * @param unit the compilation unit |
| * @return the extracted methods except the default method |
| * @throws JavaModelException if the element does not exist |
| */ |
| protected final IMethod[] getExtractedMethods(final ICompilationUnit unit) throws JavaModelException { |
| Assert.isNotNull(unit); |
| final List<IJavaElement> list= new ArrayList<>(); |
| for (int index= 0; index < fMembers.length; index++) { |
| if (fMembers[index] instanceof IMethod) { |
| final IJavaElement element= JavaModelUtil.findInCompilationUnit(unit, fMembers[index]); |
| if (element instanceof IMethod && !JdtFlags.isDefaultMethod((IMethod) element)) |
| list.add(element); |
| } |
| } |
| return list.toArray(new IMethod[list.size()]); |
| } |
| |
| /* |
| * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#getIdentifier() |
| */ |
| @Override |
| public final String getIdentifier() { |
| return IDENTIFIER; |
| } |
| |
| /* |
| * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#getProcessorName() |
| */ |
| @Override |
| public final String getProcessorName() { |
| return RefactoringCoreMessages.ExtractInterfaceProcessor_name; |
| } |
| |
| /** |
| * Returns the type where to extract an interface. |
| * |
| * @return the type where to extract an interface |
| */ |
| public final IType getType() { |
| return fSubType; |
| } |
| |
| /** |
| * Returns the new interface name. |
| * |
| * @return the new interface name |
| */ |
| public final String getTypeName() { |
| return fSuperName; |
| } |
| |
| /** |
| * Should override annotations be generated? |
| * |
| * @return <code>true</code> if annotations should be generated, <code>false</code> otherwise |
| */ |
| public final boolean isAnnotations() { |
| return fAnnotations; |
| } |
| |
| private RefactoringStatus initialize(JavaRefactoringArguments extended) { |
| String handle= extended.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT); |
| if (handle != null) { |
| final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(extended.getProject(), handle, false); |
| if (element == null || !element.exists() || element.getElementType() != IJavaElement.TYPE) |
| return JavaRefactoringDescriptorUtil.createInputFatalStatus(element, getProcessorName(), IJavaRefactorings.EXTRACT_INTERFACE); |
| else |
| fSubType= (IType) element; |
| } else |
| return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT)); |
| final String name= extended.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME); |
| if (name != null) { |
| fSuperName= name; |
| final RefactoringStatus status= checkTypeName(name); |
| if (status.hasError()) |
| return status; |
| } else |
| return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME)); |
| final String comment= extended.getAttribute(ATTRIBUTE_COMMENTS); |
| if (comment != null) { |
| fComments= Boolean.valueOf(comment).booleanValue(); |
| } else |
| return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_COMMENTS)); |
| final String instance= extended.getAttribute(ATTRIBUTE_INSTANCEOF); |
| if (instance != null) { |
| fInstanceOf= Boolean.valueOf(instance).booleanValue(); |
| } else |
| return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_INSTANCEOF)); |
| final String replace= extended.getAttribute(ATTRIBUTE_REPLACE); |
| if (replace != null) { |
| fReplace= Boolean.valueOf(replace).booleanValue(); |
| } else |
| return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_REPLACE)); |
| int count= 1; |
| final List<IJavaElement> elements= new ArrayList<>(); |
| String attribute= JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + count; |
| final RefactoringStatus status= new RefactoringStatus(); |
| while ((handle= extended.getAttribute(attribute)) != null) { |
| final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(extended.getProject(), handle, false); |
| if (element == null || !element.exists()) |
| status.merge(JavaRefactoringDescriptorUtil.createInputWarningStatus(element, getProcessorName(), IJavaRefactorings.EXTRACT_INTERFACE)); |
| else |
| elements.add(element); |
| count++; |
| attribute= JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + count; |
| } |
| fMembers= elements.toArray(new IMember[elements.size()]); |
| fSettings= JavaPreferencesSettings.getCodeGenerationSettings(fSubType.getJavaProject()); |
| if (!status.isOK()) |
| return status; |
| return new RefactoringStatus(); |
| } |
| |
| /* |
| * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#isApplicable() |
| */ |
| @Override |
| public final boolean isApplicable() throws CoreException { |
| return Checks.isAvailable(fSubType) && !fSubType.isBinary() && !fSubType.isReadOnly() && !fSubType.isAnnotation() && !fSubType.isAnonymous(); |
| } |
| |
| /** |
| * Should comments be generated? |
| * |
| * @return <code>true</code> if comments should be generated, |
| * <code>false</code> otherwise |
| */ |
| public final boolean isComments() { |
| return fComments; |
| } |
| |
| /* |
| * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#loadParticipants(org.eclipse.ltk.core.refactoring.RefactoringStatus,org.eclipse.ltk.core.refactoring.participants.SharableParticipants) |
| */ |
| @Override |
| public final RefactoringParticipant[] loadParticipants(final RefactoringStatus status, final SharableParticipants sharedParticipants) throws CoreException { |
| return new RefactoringParticipant[0]; |
| } |
| |
| /** |
| * Normalizes the indentation of the specified text. |
| * |
| * @param code |
| * the text to normalize |
| * @return the normalized text |
| * @throws JavaModelException |
| * if an error occurs |
| */ |
| protected final String normalizeText(final String code) throws JavaModelException { |
| Assert.isNotNull(code); |
| final String[] lines= Strings.convertIntoLines(code); |
| final IJavaProject project= fSubType.getJavaProject(); |
| Strings.trimIndentation(lines, project, false); |
| return Strings.concatenate(lines, StubUtility.getLineDelimiterUsed(project)); |
| } |
| |
| /** |
| * Resets the environment. |
| */ |
| protected void resetEnvironment() { |
| fSuperSource= null; |
| resetWorkingCopies(); |
| } |
| |
| @Override |
| protected final void rewriteTypeOccurrences(final TextEditBasedChangeManager manager, final ASTRequestor requestor, final CompilationUnitRewrite rewrite, final ICompilationUnit unit, final CompilationUnit node, final Set<String> replacements, final IProgressMonitor monitor) throws CoreException { |
| try { |
| monitor.beginTask("", 100); //$NON-NLS-1$ |
| monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating); |
| CompilationUnitRewrite currentRewrite= null; |
| final boolean isSubUnit= rewrite.getCu().equals(unit.getPrimary()); |
| if (isSubUnit) |
| currentRewrite= rewrite; |
| else |
| currentRewrite= new CompilationUnitRewrite(unit, node); |
| final Collection<ITypeConstraintVariable> collection= fTypeOccurrences.get(unit); |
| if (collection != null && !collection.isEmpty()) { |
| final IProgressMonitor subMonitor= new SubProgressMonitor(monitor, 100); |
| try { |
| subMonitor.beginTask("", collection.size() * 10); //$NON-NLS-1$ |
| subMonitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating); |
| TType estimate= null; |
| ISourceConstraintVariable variable= null; |
| ITypeConstraintVariable constraint= null; |
| for (final Iterator<ITypeConstraintVariable> iterator= collection.iterator(); iterator.hasNext();) { |
| variable= iterator.next(); |
| if (variable instanceof ITypeConstraintVariable) { |
| constraint= (ITypeConstraintVariable) variable; |
| estimate= (TType) constraint.getData(SuperTypeConstraintsSolver.DATA_TYPE_ESTIMATE); |
| if (estimate != null) { |
| final CompilationUnitRange range= constraint.getRange(); |
| if (isSubUnit) |
| rewriteTypeOccurrence(range, estimate, requestor, currentRewrite, node, replacements, currentRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.SuperTypeRefactoringProcessor_update_type_occurrence, SET_SUPER_TYPE)); |
| else { |
| final ASTNode result= NodeFinder.perform(node, range.getSourceRange()); |
| if (result != null) |
| rewriteTypeOccurrence(estimate, currentRewrite, result, currentRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.SuperTypeRefactoringProcessor_update_type_occurrence, SET_SUPER_TYPE)); |
| } |
| subMonitor.worked(10); |
| } |
| } |
| } |
| } finally { |
| subMonitor.done(); |
| } |
| } |
| if (!isSubUnit) { |
| final TextChange change= currentRewrite.createChange(true); |
| if (change != null) |
| manager.manage(unit, change); |
| } |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Creates the necessary text edits to replace the subtype occurrences by a |
| * supertype. |
| * |
| * @param manager |
| * the text change manager |
| * @param sourceRewrite |
| * the compilation unit of the subtype (not in working copy mode) |
| * @param superUnit |
| * the compilation unit of the supertype (in working copy mode) |
| * @param replacements |
| * the set of variable binding keys of formal parameters which |
| * must be replaced |
| * @param status |
| * the refactoring status |
| * @param monitor |
| * the progress monitor to display progress |
| * @throws CoreException |
| * if an error occurs |
| */ |
| protected final void rewriteTypeOccurrences(final TextEditBasedChangeManager manager, final CompilationUnitRewrite sourceRewrite, final ICompilationUnit superUnit, final Set<String> replacements, final RefactoringStatus status, final IProgressMonitor monitor) throws CoreException { |
| Assert.isNotNull(manager); |
| Assert.isNotNull(sourceRewrite); |
| Assert.isNotNull(superUnit); |
| Assert.isNotNull(replacements); |
| Assert.isNotNull(status); |
| Assert.isNotNull(monitor); |
| try { |
| monitor.beginTask("", 300); //$NON-NLS-1$ |
| monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating); |
| final ICompilationUnit subUnit= getSharedWorkingCopy(fSubType.getCompilationUnit().getPrimary(), new SubProgressMonitor(monitor, 20)); |
| final ITextFileBuffer buffer= RefactoringFileBuffers.acquire(fSubType.getCompilationUnit()); |
| final ASTRewrite rewrite= sourceRewrite.getASTRewrite(); |
| try { |
| final IDocument document= new Document(buffer.getDocument().get()); |
| try { |
| rewrite.rewriteAST(document, fSubType.getJavaProject().getOptions(true)).apply(document, TextEdit.UPDATE_REGIONS); |
| } catch (MalformedTreeException exception) { |
| JavaPlugin.log(exception); |
| } catch (BadLocationException exception) { |
| JavaPlugin.log(exception); |
| } |
| subUnit.getBuffer().setContents(document.get()); |
| } finally { |
| RefactoringFileBuffers.release(fSubType.getCompilationUnit()); |
| } |
| JavaModelUtil.reconcile(subUnit); |
| final IJavaProject project= subUnit.getJavaProject(); |
| final ASTParser parser= ASTParser.newParser(ASTProvider.SHARED_AST_LEVEL); |
| parser.setWorkingCopyOwner(fOwner); |
| parser.setResolveBindings(true); |
| parser.setProject(project); |
| parser.setCompilerOptions(RefactoringASTParser.getCompilerOptions(project)); |
| parser.createASTs(new ICompilationUnit[] { subUnit}, new String[0], new ASTRequestor() { |
| |
| @Override |
| public final void acceptAST(final ICompilationUnit unit, final CompilationUnit node) { |
| try { |
| final IType subType= (IType) JavaModelUtil.findInCompilationUnit(unit, fSubType); |
| final AbstractTypeDeclaration subDeclaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(subType, node); |
| if (subDeclaration != null) { |
| final ITypeBinding subBinding= subDeclaration.resolveBinding(); |
| if (subBinding != null) { |
| String name= null; |
| ITypeBinding superBinding= null; |
| final ITypeBinding[] superBindings= subBinding.getInterfaces(); |
| for (int index= 0; index < superBindings.length; index++) { |
| name= superBindings[index].getName(); |
| if (name.startsWith(fSuperName) && superBindings[index].getTypeArguments().length == subBinding.getTypeParameters().length) |
| superBinding= superBindings[index]; |
| } |
| if (superBinding != null) { |
| solveSuperTypeConstraints(unit, node, subType, subBinding, superBinding, new SubProgressMonitor(monitor, 80), status); |
| if (!status.hasFatalError()) { |
| rewriteTypeOccurrences(manager, this, sourceRewrite, unit, node, replacements, status, new SubProgressMonitor(monitor, 200)); |
| if (manager.containsChangesIn(superUnit)) { |
| final TextEditBasedChange change= manager.get(superUnit); |
| if (change instanceof TextChange) { |
| final TextEdit edit= ((TextChange) change).getEdit(); |
| if (edit != null) { |
| final IDocument document= new Document(superUnit.getBuffer().getContents()); |
| try { |
| edit.apply(document, TextEdit.UPDATE_REGIONS); |
| } catch (MalformedTreeException exception) { |
| JavaPlugin.log(exception); |
| status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_internal_error)); |
| } catch (BadLocationException exception) { |
| JavaPlugin.log(exception); |
| status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_internal_error)); |
| } |
| fSuperSource= document.get(); |
| manager.remove(superUnit); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } catch (JavaModelException exception) { |
| JavaPlugin.log(exception); |
| status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_internal_error)); |
| } |
| } |
| |
| @Override |
| public final void acceptBinding(final String key, final IBinding binding) { |
| // Do nothing |
| } |
| }, new NullProgressMonitor()); |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Determines whether override annotations should be generated. |
| * |
| * @param annotations <code>true</code> to generate override annotations, <code>false</code> otherwise |
| */ |
| public final void setAnnotations(final boolean annotations) { |
| fAnnotations= annotations; |
| } |
| |
| /** |
| * Determines whether comments should be generated. |
| * |
| * @param comments |
| * <code>true</code> to generate comments, <code>false</code> |
| * otherwise |
| */ |
| public final void setComments(final boolean comments) { |
| fComments= comments; |
| } |
| |
| /** |
| * Sets the members to be extracted. |
| * |
| * @param members |
| * the members to be extracted |
| * @throws JavaModelException |
| * if an error occurs |
| */ |
| public final void setExtractedMembers(final IMember[] members) throws JavaModelException { |
| fMembers= members; |
| } |
| |
| /** |
| * Sets the new interface name. |
| * |
| * @param name |
| * the new interface name |
| */ |
| public final void setTypeName(final String name) { |
| Assert.isNotNull(name); |
| fSuperName= name; |
| } |
| } |