| /******************************************************************************* |
| * Copyright (c) 2000, 2018 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.corext.refactoring.rename; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map.Entry; |
| import java.util.Set; |
| |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.SubProgressMonitor; |
| |
| import org.eclipse.core.resources.IContainer; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IFolder; |
| import org.eclipse.core.resources.IResource; |
| |
| import org.eclipse.text.edits.MalformedTreeException; |
| import org.eclipse.text.edits.ReplaceEdit; |
| import org.eclipse.text.edits.TextEdit; |
| |
| import org.eclipse.jface.util.Util; |
| |
| import org.eclipse.ltk.core.refactoring.Change; |
| import org.eclipse.ltk.core.refactoring.CompositeChange; |
| import org.eclipse.ltk.core.refactoring.IResourceMapper; |
| import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; |
| import org.eclipse.ltk.core.refactoring.RefactoringStatus; |
| import org.eclipse.ltk.core.refactoring.RefactoringStatusContext; |
| import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; |
| import org.eclipse.ltk.core.refactoring.participants.RenameArguments; |
| |
| import org.eclipse.jdt.core.Flags; |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.IImportDeclaration; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IMethod; |
| import org.eclipse.jdt.core.IOrdinaryClassFile; |
| import org.eclipse.jdt.core.IPackageFragment; |
| import org.eclipse.jdt.core.IPackageFragmentRoot; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.core.Signature; |
| import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; |
| import org.eclipse.jdt.core.refactoring.IJavaElementMapper; |
| import org.eclipse.jdt.core.refactoring.IJavaRefactorings; |
| import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor; |
| import org.eclipse.jdt.core.refactoring.descriptors.RenameJavaElementDescriptor; |
| import org.eclipse.jdt.core.search.IJavaSearchConstants; |
| import org.eclipse.jdt.core.search.IJavaSearchScope; |
| import org.eclipse.jdt.core.search.SearchEngine; |
| import org.eclipse.jdt.core.search.SearchMatch; |
| import org.eclipse.jdt.core.search.SearchPattern; |
| import org.eclipse.jdt.core.search.SearchRequestor; |
| |
| import org.eclipse.jdt.internal.core.refactoring.descriptors.RefactoringSignatureDescriptorFactory; |
| import org.eclipse.jdt.internal.corext.refactoring.Checks; |
| import org.eclipse.jdt.internal.corext.refactoring.CollectingSearchRequestor; |
| import org.eclipse.jdt.internal.corext.refactoring.CuCollectingSearchRequestor; |
| 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.RefactoringAvailabilityTester; |
| import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; |
| import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory; |
| import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine; |
| import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup; |
| import org.eclipse.jdt.internal.corext.refactoring.base.ReferencesInBinaryContext; |
| import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange; |
| import org.eclipse.jdt.internal.corext.refactoring.changes.RenamePackageChange; |
| import org.eclipse.jdt.internal.corext.refactoring.changes.TextChangeCompatibility; |
| import org.eclipse.jdt.internal.corext.refactoring.participants.JavaProcessors; |
| import org.eclipse.jdt.internal.corext.refactoring.rename.RenamePackageProcessor.ImportsManager.ImportChange; |
| import org.eclipse.jdt.internal.corext.refactoring.tagging.IQualifiedNameUpdating; |
| import org.eclipse.jdt.internal.corext.refactoring.tagging.IReferenceUpdating; |
| import org.eclipse.jdt.internal.corext.refactoring.tagging.ITextUpdating; |
| import org.eclipse.jdt.internal.corext.refactoring.util.Changes; |
| import org.eclipse.jdt.internal.corext.refactoring.util.CommentAnalyzer; |
| import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil; |
| import org.eclipse.jdt.internal.corext.refactoring.util.JavaStatusContext; |
| import org.eclipse.jdt.internal.corext.refactoring.util.QualifiedNameFinder; |
| import org.eclipse.jdt.internal.corext.refactoring.util.QualifiedNameSearchResult; |
| import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil; |
| import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager; |
| import org.eclipse.jdt.internal.corext.util.Messages; |
| import org.eclipse.jdt.internal.corext.util.Resources; |
| import org.eclipse.jdt.internal.corext.util.SearchUtils; |
| |
| import org.eclipse.jdt.ui.JavaElementLabels; |
| import org.eclipse.jdt.ui.refactoring.RefactoringSaveHelper; |
| |
| import org.eclipse.jdt.internal.ui.JavaPlugin; |
| |
| import org.eclipse.jdt.internal.core.manipulation.StubUtility; |
| import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels; |
| |
| public class RenamePackageProcessor extends JavaRenameProcessor implements |
| IReferenceUpdating, ITextUpdating, IQualifiedNameUpdating, IResourceMapper, IJavaElementMapper { |
| |
| private static final String ATTRIBUTE_QUALIFIED= "qualified"; //$NON-NLS-1$ |
| private static final String ATTRIBUTE_TEXTUAL_MATCHES= "textual"; //$NON-NLS-1$ |
| private static final String ATTRIBUTE_PATTERNS= "patterns"; //$NON-NLS-1$ |
| private static final String ATTRIBUTE_HIERARCHICAL= "hierarchical"; //$NON-NLS-1$ |
| |
| private IPackageFragment fPackage; |
| |
| private TextChangeManager fChangeManager; |
| private ImportsManager fImportsManager; |
| private QualifiedNameSearchResult fQualifiedNameSearchResult; |
| |
| private boolean fUpdateReferences; |
| private boolean fUpdateTextualMatches; |
| private boolean fUpdateQualifiedNames; |
| private String fFilePatterns; |
| private boolean fRenameSubpackages; |
| |
| public static final String IDENTIFIER= "org.eclipse.jdt.ui.renamePackageProcessor"; //$NON-NLS-1$ |
| private RenamePackageChange fRenamePackageChange; |
| |
| /** |
| * Creates a new rename package processor. |
| * @param fragment the package fragment, or <code>null</code> if invoked by scripting |
| */ |
| public RenamePackageProcessor(IPackageFragment fragment) { |
| fPackage= fragment; |
| if (fPackage != null) |
| setNewElementName(fPackage.getElementName()); |
| fUpdateReferences= true; |
| fUpdateTextualMatches= false; |
| fRenameSubpackages= false; |
| } |
| |
| public RenamePackageProcessor(JavaRefactoringArguments arguments, RefactoringStatus status) { |
| this(null); |
| status.merge(initialize(arguments)); |
| } |
| |
| @Override |
| public String getIdentifier() { |
| return IDENTIFIER; |
| } |
| |
| @Override |
| public boolean isApplicable() throws CoreException { |
| return RefactoringAvailabilityTester.isRenameAvailable(fPackage); |
| } |
| |
| @Override |
| public String getProcessorName(){ |
| return RefactoringCoreMessages.RenamePackageRefactoring_name; |
| } |
| |
| @Override |
| protected String[] getAffectedProjectNatures() throws CoreException { |
| return JavaProcessors.computeAffectedNatures(fPackage); |
| } |
| |
| @Override |
| public Object[] getElements() { |
| return new Object[] {fPackage}; |
| } |
| |
| @Override |
| protected RenameModifications computeRenameModifications() throws CoreException { |
| RenameModifications result= new RenameModifications(); |
| result.rename(fPackage, new RenameArguments(getNewElementName(), getUpdateReferences()), fRenameSubpackages); |
| return result; |
| } |
| |
| @Override |
| protected IFile[] getChangedFiles() throws CoreException { |
| Set<IFile> combined= new HashSet<>(); |
| combined.addAll(Arrays.asList(ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits()))); |
| if (fRenameSubpackages) { |
| for (IPackageFragment pack : JavaElementUtil.getPackageAndSubpackages(fPackage)) { |
| combined.addAll(Arrays.asList(ResourceUtil.getFiles(pack.getCompilationUnits()))); |
| } |
| } else { |
| combined.addAll(Arrays.asList(ResourceUtil.getFiles(fPackage.getCompilationUnits()))); |
| } |
| if (fQualifiedNameSearchResult != null) |
| combined.addAll(Arrays.asList(fQualifiedNameSearchResult.getAllFiles())); |
| return combined.toArray(new IFile[combined.size()]); |
| } |
| |
| @Override |
| public int getSaveMode() { |
| return RefactoringSaveHelper.SAVE_ALL; |
| } |
| |
| //---- ITextUpdating ------------------------------------------------- |
| |
| @Override |
| public boolean canEnableTextUpdating() { |
| return true; |
| } |
| |
| @Override |
| public boolean getUpdateTextualMatches() { |
| return fUpdateTextualMatches; |
| } |
| |
| @Override |
| public void setUpdateTextualMatches(boolean update) { |
| fUpdateTextualMatches= update; |
| } |
| |
| //---- IReferenceUpdating -------------------------------------- |
| |
| @Override |
| public void setUpdateReferences(boolean update) { |
| fUpdateReferences= update; |
| } |
| |
| @Override |
| public boolean getUpdateReferences(){ |
| return fUpdateReferences; |
| } |
| |
| //---- IQualifiedNameUpdating ---------------------------------- |
| |
| @Override |
| public boolean canEnableQualifiedNameUpdating() { |
| return !fPackage.isDefaultPackage(); |
| } |
| |
| @Override |
| public boolean getUpdateQualifiedNames() { |
| return fUpdateQualifiedNames; |
| } |
| |
| @Override |
| public void setUpdateQualifiedNames(boolean update) { |
| fUpdateQualifiedNames= update; |
| } |
| |
| @Override |
| public String getFilePatterns() { |
| return fFilePatterns; |
| } |
| |
| @Override |
| public void setFilePatterns(String patterns) { |
| Assert.isNotNull(patterns); |
| fFilePatterns= patterns; |
| } |
| |
| //---- IResourceMapper ---------------------------------- |
| |
| @Override |
| public IResource getRefactoredResource(IResource element) { |
| IFolder packageFolder= (IFolder) fPackage.getResource(); |
| if (packageFolder == null) |
| return element; |
| |
| IContainer newPackageFolder= (IContainer) getNewPackage().getResource(); |
| |
| if (packageFolder.equals(element)) |
| return newPackageFolder; |
| |
| IPath packagePath= packageFolder.getProjectRelativePath(); |
| IPath elementPath= element.getProjectRelativePath(); |
| |
| if (packagePath.isPrefixOf(elementPath)) { |
| if (fRenameSubpackages || (element instanceof IFile && packageFolder.equals(element.getParent()))) { |
| IPath pathInPackage= elementPath.removeFirstSegments(packagePath.segmentCount()); |
| if (element instanceof IFile) |
| return newPackageFolder.getFile(pathInPackage); |
| else |
| return newPackageFolder.getFolder(pathInPackage); |
| } |
| } |
| return element; |
| } |
| |
| //---- IJavaElementMapper ---------------------------------- |
| |
| @Override |
| public IJavaElement getRefactoredJavaElement(IJavaElement original) { |
| return new GenericRefactoringHandleTransplanter() { |
| @Override |
| protected IPackageFragment transplantHandle(IPackageFragmentRoot parent, IPackageFragment element) { |
| if (! fRenameSubpackages) { |
| if (fPackage.equals(element)) |
| return getNewPackage(); |
| } else { |
| String packName= element.getElementName(); |
| String packageName= fPackage.getElementName(); |
| if (fPackage.getParent().equals(parent) |
| && packName.startsWith(packageName + '.')) { |
| String newPackName= getNewElementName() + packName.substring(packageName.length() - 1); |
| return getPackageFragmentRoot().getPackageFragment(newPackName); |
| } |
| } |
| return super.transplantHandle(parent, element); |
| } |
| |
| @Override |
| protected IMethod transplantHandle(IType parent, IMethod element) { |
| String[] parameterTypes= resolveParameterTypes(element); |
| return parent.getMethod(element.getElementName(), parameterTypes); |
| } |
| |
| private String[] resolveParameterTypes(IMethod method) { |
| final String[] oldParameterTypes= method.getParameterTypes(); |
| final String[] newparams= new String[oldParameterTypes.length]; |
| |
| final String[] possibleOldSigs= new String[2]; |
| //using type signature, since there is no package signature |
| possibleOldSigs[0]= Signature.createTypeSignature(fPackage.getElementName(), false); |
| possibleOldSigs[1]= Signature.createTypeSignature(fPackage.getElementName(), true); |
| |
| final String[] possibleNewSigs= new String[2]; |
| possibleNewSigs[0]= Signature.createTypeSignature(getNewElementName(), false); |
| possibleNewSigs[1]= Signature.createTypeSignature(getNewElementName(), true); |
| |
| // Textually replace all occurrences |
| // This handles stuff like Map<SomeClass, some.package.SomeClass> |
| for (int i= 0; i < oldParameterTypes.length; i++) { |
| newparams[i]= oldParameterTypes[i]; |
| for (int j= 0; j < possibleOldSigs.length; j++) { |
| newparams[i]= Util.replaceAll(newparams[i], possibleOldSigs[j], possibleNewSigs[j]); |
| } |
| } |
| return newparams; |
| } |
| }.transplantHandle(original); |
| } |
| |
| //---- |
| |
| public boolean canEnableRenameSubpackages() throws JavaModelException { |
| return fPackage.hasSubpackages(); |
| } |
| |
| public boolean getRenameSubpackages() { |
| return fRenameSubpackages; |
| } |
| |
| public void setRenameSubpackages(boolean rename) { |
| fRenameSubpackages= rename; |
| } |
| |
| //---- IRenameProcessor ---------------------------------------------- |
| |
| @Override |
| public final String getCurrentElementName(){ |
| return fPackage.getElementName(); |
| } |
| |
| @Override |
| public String getCurrentElementQualifier() { |
| return ""; //$NON-NLS-1$ |
| } |
| |
| @Override |
| public RefactoringStatus checkNewElementName(String newName) throws CoreException { |
| Assert.isNotNull(newName, "new name"); //$NON-NLS-1$ |
| RefactoringStatus result= Checks.checkPackageName(newName, fPackage); |
| if (result.hasFatalError()) |
| return result; |
| if (Checks.isAlreadyNamed(fPackage, newName)) { |
| result.addFatalError(RefactoringCoreMessages.RenamePackageRefactoring_another_name); |
| return result; |
| } |
| result.merge(checkPackageInCurrentRoot(newName)); |
| return result; |
| } |
| |
| @Override |
| public Object getNewElement(){ |
| return getNewPackage(); |
| } |
| |
| private IPackageFragment getNewPackage() { |
| IPackageFragmentRoot root= getPackageFragmentRoot(); |
| return root.getPackageFragment(getNewElementName()); |
| } |
| |
| @Override |
| public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException { |
| return new RefactoringStatus(); |
| } |
| |
| @Override |
| protected RefactoringStatus doCheckFinalConditions(IProgressMonitor pm, CheckConditionsContext context) throws CoreException { |
| try{ |
| pm.beginTask("", 23 + (fUpdateQualifiedNames ? 10 : 0) + (fUpdateTextualMatches ? 10 : 0)); //$NON-NLS-1$ |
| pm.setTaskName(RefactoringCoreMessages.RenamePackageRefactoring_checking); |
| RefactoringStatus result= new RefactoringStatus(); |
| result.merge(checkNewElementName(getNewElementName())); |
| pm.worked(1); |
| result.merge(checkForMainAndNativeMethods()); |
| pm.worked(2); |
| |
| if (fPackage.isReadOnly()){ |
| String message= Messages.format(RefactoringCoreMessages.RenamePackageRefactoring_Packagered_only, getElementLabel(fPackage)); |
| result.addFatalError(message); |
| } else if (Resources.isReadOnly(fPackage.getResource())) { |
| String message= Messages.format(RefactoringCoreMessages.RenamePackageRefactoring_resource_read_only, getElementLabel(fPackage)); |
| result.addError(message); |
| } |
| |
| result.merge(checkPackageName(getNewElementName())); |
| if (result.hasFatalError()) |
| return result; |
| |
| fChangeManager= new TextChangeManager(); |
| fImportsManager= new ImportsManager(); |
| |
| SubProgressMonitor subPm= new SubProgressMonitor(pm, 16); |
| if (fRenameSubpackages) { |
| IPackageFragment[] allSubpackages= JavaElementUtil.getPackageAndSubpackages(fPackage); |
| subPm.beginTask("", allSubpackages.length); //$NON-NLS-1$ |
| for (IPackageFragment pack : allSubpackages) { |
| new PackageRenamer(pack, this, fChangeManager, fImportsManager).doRename(new SubProgressMonitor(subPm, 1), result); |
| } |
| subPm.done(); |
| } else { |
| new PackageRenamer(fPackage, this, fChangeManager, fImportsManager).doRename(subPm, result); |
| } |
| |
| fImportsManager.rewriteImports(fChangeManager, new SubProgressMonitor(pm, 3)); |
| |
| if (fUpdateTextualMatches) { |
| pm.subTask(RefactoringCoreMessages.RenamePackageRefactoring_searching_text); |
| TextMatchUpdater.perform(new SubProgressMonitor(pm, 10), RefactoringScopeFactory.create(fPackage), this, fChangeManager, new SearchResultGroup[0]); |
| } |
| |
| if (fUpdateQualifiedNames) |
| computeQualifiedNameMatches(new SubProgressMonitor(pm, 10)); |
| |
| return result; |
| } finally{ |
| pm.done(); |
| } |
| } |
| |
| public IPackageFragment getPackage() { |
| return fPackage; |
| } |
| |
| private RefactoringStatus checkForMainAndNativeMethods() throws CoreException{ |
| RefactoringStatus result= new RefactoringStatus(); |
| if (fRenameSubpackages) { |
| for (IPackageFragment pack : JavaElementUtil.getPackageAndSubpackages(fPackage)) { |
| for (ICompilationUnit cu : pack.getCompilationUnits()) { |
| result.merge(Checks.checkForMainAndNativeMethods(cu)); |
| } |
| } |
| } else { |
| for (ICompilationUnit cu : fPackage.getCompilationUnits()) { |
| result.merge(Checks.checkForMainAndNativeMethods(cu)); |
| } |
| } |
| return result; |
| } |
| |
| /* |
| * returns true if the new name is ok if the specified root. |
| * if a package fragment with this name exists and has java resources, |
| * then the name is not ok. |
| */ |
| public static boolean isPackageNameOkInRoot(String newName, IPackageFragmentRoot root) throws CoreException { |
| IPackageFragment pack= root.getPackageFragment(newName); |
| if (! pack.exists()) |
| return true; |
| else if (pack.containsJavaResources()) |
| return false; |
| else if (pack.getNonJavaResources().length != 0) |
| return false; |
| else |
| return true; |
| } |
| |
| private RefactoringStatus checkPackageInCurrentRoot(String newName) throws CoreException { |
| if (fRenameSubpackages) { |
| String currentName= getCurrentElementName(); |
| if (isAncestorPackage(currentName, newName)) { |
| // renaming to subpackage (a -> a.b) is always OK, since all subpackages are also renamed |
| return null; |
| } |
| if (! isAncestorPackage(newName, currentName)) { |
| // renaming to an unrelated package |
| if (! isPackageNameOkInRoot(newName, getPackageFragmentRoot())) { |
| return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.RenamePackageRefactoring_package_exists); |
| } |
| } |
| // renaming to superpackage (a.b -> a) or another package is OK iff |
| // 'a.b' does not contain any subpackage that would collide with another subpackage of 'a' |
| // (e.g. a.b.c collides if a.c already exists, but a.b.b does not collide with a.b) |
| for (IPackageFragment pack : JavaElementUtil.getPackageAndSubpackages(fPackage)) { |
| String newPack= newName + pack.getElementName().substring(currentName.length()); |
| if (! isAncestorPackage(currentName, newPack) && ! isPackageNameOkInRoot(newPack, getPackageFragmentRoot())) { |
| String msg= Messages.format(RefactoringCoreMessages.RenamePackageProcessor_subpackage_collides, BasicElementLabels.getJavaElementName(newPack)); |
| return RefactoringStatus.createFatalErrorStatus(msg); |
| } |
| } |
| return null; |
| |
| } else if (! isPackageNameOkInRoot(newName, getPackageFragmentRoot())) { |
| return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.RenamePackageRefactoring_package_exists); |
| } else { |
| return null; |
| } |
| } |
| |
| private boolean isAncestorPackage(String ancestor, String descendant) { |
| int a= ancestor.length(); |
| int d= descendant.length(); |
| if (a == d || (a < d && descendant.charAt(a) == '.')) |
| return descendant.startsWith(ancestor); |
| else |
| return false; |
| } |
| |
| private IPackageFragmentRoot getPackageFragmentRoot() { |
| return ((IPackageFragmentRoot)fPackage.getParent()); |
| } |
| |
| private RefactoringStatus checkPackageName(String newName) throws CoreException { |
| RefactoringStatus status= new RefactoringStatus(); |
| Set<String> topLevelTypeNames= getTopLevelTypeNames(); |
| for (IPackageFragmentRoot root : fPackage.getJavaProject().getPackageFragmentRoots()) { |
| if (! isPackageNameOkInRoot(newName, root)) { |
| String rootLabel = JavaElementLabels.getElementLabel(root, JavaElementLabels.ALL_DEFAULT); |
| String newPackageName= BasicElementLabels.getJavaElementName(getNewElementName()); |
| String message= Messages.format(RefactoringCoreMessages.RenamePackageRefactoring_aleady_exists, new Object[]{ newPackageName, rootLabel}); |
| status.merge(RefactoringStatus.createWarningStatus(message)); |
| status.merge(checkTypeNameConflicts(root, newName, topLevelTypeNames)); |
| } |
| } |
| return status; |
| } |
| |
| private Set<String> getTopLevelTypeNames() throws CoreException { |
| ICompilationUnit[] cus= fPackage.getCompilationUnits(); |
| Set<String> result= new HashSet<>(2 * cus.length); |
| for (ICompilationUnit cu : cus) { |
| result.addAll(getTopLevelTypeNames(cu)); |
| } |
| return result; |
| } |
| |
| private static Collection<String> getTopLevelTypeNames(ICompilationUnit iCompilationUnit) throws CoreException { |
| IType[] types= iCompilationUnit.getTypes(); |
| List<String> result= new ArrayList<>(types.length); |
| for (IType type : types) { |
| result.add(type.getElementName()); |
| } |
| return result; |
| } |
| |
| private RefactoringStatus checkTypeNameConflicts(IPackageFragmentRoot root, String newName, Set<String> topLevelTypeNames) throws CoreException { |
| IPackageFragment otherPack= root.getPackageFragment(newName); |
| if (fPackage.equals(otherPack)) |
| return null; |
| RefactoringStatus result= new RefactoringStatus(); |
| for (ICompilationUnit cu : otherPack.getCompilationUnits()) { |
| result.merge(checkTypeNameConflicts(cu, topLevelTypeNames)); |
| } |
| return result; |
| } |
| |
| private RefactoringStatus checkTypeNameConflicts(ICompilationUnit iCompilationUnit, Set<String> topLevelTypeNames) throws CoreException { |
| RefactoringStatus result= new RefactoringStatus(); |
| |
| for (IType type : iCompilationUnit.getTypes()) { |
| String name= type.getElementName(); |
| if (topLevelTypeNames.contains(name)) { |
| String[] keys= {getElementLabel(iCompilationUnit.getParent()), getElementLabel(type)}; |
| String msg= Messages.format(RefactoringCoreMessages.RenamePackageRefactoring_contains_type, keys); |
| RefactoringStatusContext context= JavaStatusContext.create(type); |
| result.addError(msg, context); |
| } |
| } |
| return result; |
| } |
| |
| @Override |
| public Change createChange(IProgressMonitor monitor) throws CoreException { |
| try { |
| monitor.beginTask(RefactoringCoreMessages.RenamePackageRefactoring_creating_change, 1); |
| final RenameJavaElementDescriptor descriptor= createRefactoringDescriptor(); |
| final DynamicValidationRefactoringChange result= new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.RenamePackageRefactoring_change_name); |
| result.addAll(fChangeManager.getAllChanges()); |
| fRenamePackageChange= new RenamePackageChange( fPackage, getNewElementName(), fRenameSubpackages); |
| result.add(fRenamePackageChange); |
| monitor.worked(1); |
| return result; |
| } finally { |
| fChangeManager= null; |
| fImportsManager= null; |
| monitor.done(); |
| } |
| } |
| |
| private RenameJavaElementDescriptor createRefactoringDescriptor() { |
| String project= null; |
| IJavaProject javaProject= fPackage.getJavaProject(); |
| if (javaProject != null) |
| project= javaProject.getElementName(); |
| final int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE | RefactoringDescriptor.MULTI_CHANGE; |
| final String description= Messages.format(RefactoringCoreMessages.RenamePackageProcessor_descriptor_description_short, getElementLabel(fPackage)); |
| final String header= Messages.format(RefactoringCoreMessages.RenamePackageProcessor_descriptor_description, new String[] { getElementLabel(fPackage), getNewElementName()}); |
| final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header); |
| if (fRenameSubpackages) |
| comment.addSetting(RefactoringCoreMessages.RenamePackageProcessor_rename_subpackages); |
| final RenameJavaElementDescriptor descriptor= RefactoringSignatureDescriptorFactory.createRenameJavaElementDescriptor(IJavaRefactorings.RENAME_PACKAGE); |
| descriptor.setProject(project); |
| descriptor.setDescription(description); |
| descriptor.setComment(comment.asString()); |
| descriptor.setFlags(flags); |
| descriptor.setJavaElement(fPackage); |
| descriptor.setNewName(getNewElementName()); |
| descriptor.setUpdateReferences(fUpdateReferences); |
| descriptor.setUpdateTextualOccurrences(fUpdateTextualMatches); |
| descriptor.setUpdateQualifiedNames(fUpdateQualifiedNames); |
| if (fUpdateQualifiedNames && fFilePatterns != null && !"".equals(fFilePatterns)) //$NON-NLS-1$ |
| descriptor.setFileNamePatterns(fFilePatterns); |
| descriptor.setUpdateHierarchy(fRenameSubpackages); |
| return descriptor; |
| } |
| |
| private static String getElementLabel(IJavaElement javaElement) { |
| return JavaElementLabels.getElementLabel(javaElement, JavaElementLabels.ALL_DEFAULT); |
| } |
| |
| @Override |
| public Change postCreateChange(Change[] participantChanges, IProgressMonitor pm) throws CoreException { |
| if (fQualifiedNameSearchResult != null) { |
| CompositeChange parent= (CompositeChange) fRenamePackageChange.getParent(); |
| try { |
| /* |
| * Sneak text changes in before the package rename to ensure |
| * modified files are still at original location (see |
| * https://bugs.eclipse.org/bugs/show_bug.cgi?id=154238) |
| */ |
| parent.remove(fRenamePackageChange); |
| parent.add(fQualifiedNameSearchResult.getSingleChange(Changes.getModifiedFiles(participantChanges))); |
| } finally { |
| fQualifiedNameSearchResult= null; |
| parent.add(fRenamePackageChange); |
| fRenamePackageChange= null; |
| } |
| } |
| return null; |
| } |
| |
| private void computeQualifiedNameMatches(IProgressMonitor pm) { |
| if (fQualifiedNameSearchResult == null) |
| fQualifiedNameSearchResult= new QualifiedNameSearchResult(); |
| QualifiedNameFinder.process(fQualifiedNameSearchResult, fPackage.getElementName(), getNewElementName(), |
| fFilePatterns, fPackage.getJavaProject().getProject(), pm); |
| } |
| |
| public String getNewPackageName(String oldSubPackageName) { |
| String oldPackageName= getPackage().getElementName(); |
| return getNewElementName() + oldSubPackageName.substring(oldPackageName.length()); |
| } |
| |
| private static class PackageRenamer { |
| private final IPackageFragment fPackage; |
| private final RenamePackageProcessor fProcessor; |
| private final TextChangeManager fTextChangeManager; |
| private final ImportsManager fImportsManager; |
| |
| /** references to fPackage (can include star imports which also import namesake package fragments) */ |
| private SearchResultGroup[] fOccurrences; |
| |
| /** References in CUs from fOccurrences and fPackage to types in namesake packages. |
| * <p>These need an import with the old package name. |
| * <p>- from fOccurrences (without namesakes): may have shared star import |
| * (star-import not updated here, but for fOccurrences) |
| * <p>- from fPackage: may have unimported references to types of namesake packages |
| * <p>- both: may have unused imports of namesake packages. |
| * <p>Mutable List of SearchResultGroup. */ |
| private List<SearchResultGroup> fReferencesToTypesInNamesakes; |
| |
| /** References in CUs from namesake packages to types in fPackage. |
| * <p>These need an import with the new package name. |
| * <p>Mutable List of SearchResultGroup. */ |
| private List<SearchResultGroup> fReferencesToTypesInPackage; |
| |
| public PackageRenamer(IPackageFragment pack, RenamePackageProcessor processor, TextChangeManager textChangeManager, ImportsManager importsManager) { |
| fPackage= pack; |
| fProcessor= processor; |
| fTextChangeManager= textChangeManager; |
| fImportsManager= importsManager; |
| } |
| |
| void doRename(IProgressMonitor pm, RefactoringStatus result) throws CoreException { |
| pm.beginTask("", 16); //$NON-NLS-1$ |
| if (fProcessor.getUpdateReferences()){ |
| pm.setTaskName(RefactoringCoreMessages.RenamePackageRefactoring_searching); |
| |
| String binaryRefsDescription= Messages.format(RefactoringCoreMessages.ReferencesInBinaryContext_ref_in_binaries_description , getElementLabel(fPackage)); |
| ReferencesInBinaryContext binaryRefs= new ReferencesInBinaryContext(binaryRefsDescription); |
| |
| fOccurrences= getReferences(new SubProgressMonitor(pm, 4), binaryRefs, result); |
| fReferencesToTypesInNamesakes= getReferencesToTypesInNamesakes(new SubProgressMonitor(pm, 4), result); |
| fReferencesToTypesInPackage= getReferencesToTypesInPackage(new SubProgressMonitor(pm, 4), binaryRefs, result); |
| binaryRefs.addErrorIfNecessary(result); |
| |
| pm.setTaskName(RefactoringCoreMessages.RenamePackageRefactoring_checking); |
| result.merge(analyzeAffectedCompilationUnits()); |
| pm.worked(1); |
| } else { |
| fOccurrences= new SearchResultGroup[0]; |
| pm.worked(13); |
| } |
| |
| if (result.hasFatalError()) |
| return; |
| |
| if (fProcessor.getUpdateReferences()) |
| addReferenceUpdates(new SubProgressMonitor(pm, 3)); |
| else |
| pm.worked(3); |
| |
| pm.done(); |
| } |
| |
| private SearchResultGroup[] getReferences(IProgressMonitor pm, ReferencesInBinaryContext binaryRefs, RefactoringStatus status) throws CoreException { |
| IJavaSearchScope scope= RefactoringScopeFactory.create(fPackage, true, false); |
| SearchPattern pattern= SearchPattern.createPattern(fPackage, IJavaSearchConstants.REFERENCES); |
| CollectingSearchRequestor requestor= new CuCollectingSearchRequestor(binaryRefs); |
| return RefactoringSearchEngine.search(pattern, scope, requestor, pm, status); |
| } |
| |
| private void addReferenceUpdates(IProgressMonitor pm) throws CoreException { |
| pm.beginTask("", fOccurrences.length + fReferencesToTypesInPackage.size() + fReferencesToTypesInNamesakes.size()); //$NON-NLS-1$ |
| for (SearchResultGroup occurrence : fOccurrences) { |
| ICompilationUnit cu= occurrence.getCompilationUnit(); |
| if (cu == null) |
| continue; |
| for (SearchMatch result : occurrence.getSearchResults()) { |
| IJavaElement enclosingElement= SearchUtils.getEnclosingJavaElement(result); |
| if (enclosingElement instanceof IImportDeclaration) { |
| IImportDeclaration importDeclaration= (IImportDeclaration) enclosingElement; |
| String updatedImport= getUpdatedImport(importDeclaration); |
| updateImport(cu, importDeclaration, updatedImport); |
| } else { // is reference |
| TextChangeCompatibility.addTextEdit(fTextChangeManager.get(cu), RefactoringCoreMessages.RenamePackageRefactoring_update_reference, createTextChange(result)); |
| } |
| } |
| if (fReferencesToTypesInNamesakes.size() != 0) { |
| SearchResultGroup typeRefsRequiringOldNameImport= extractGroupFor(cu, fReferencesToTypesInNamesakes); |
| if (typeRefsRequiringOldNameImport != null) |
| addTypeImports(typeRefsRequiringOldNameImport); |
| } |
| if (fReferencesToTypesInPackage.size() != 0) { |
| SearchResultGroup typeRefsRequiringNewNameImport= extractGroupFor(cu, fReferencesToTypesInPackage); |
| if (typeRefsRequiringNewNameImport != null) |
| updateTypeImports(typeRefsRequiringNewNameImport); |
| } |
| pm.worked(1); |
| } |
| |
| if (fReferencesToTypesInNamesakes.size() != 0) { |
| for (SearchResultGroup referencesToTypesInNamesakes : fReferencesToTypesInNamesakes) { |
| addTypeImports(referencesToTypesInNamesakes); |
| pm.worked(1); |
| } |
| } |
| if (fReferencesToTypesInPackage.size() != 0) { |
| for (SearchResultGroup namesakeReferencesToPackage : fReferencesToTypesInPackage) { |
| updateTypeImports(namesakeReferencesToPackage); |
| pm.worked(1); |
| } |
| } |
| pm.done(); |
| } |
| |
| /** Removes the found SearchResultGroup from the list iff found. |
| * @param cu the cu |
| * @param searchResultGroups List of SearchResultGroup |
| * @return the SearchResultGroup for cu, or null iff not found */ |
| private static SearchResultGroup extractGroupFor(ICompilationUnit cu, List<SearchResultGroup> searchResultGroups) { |
| for (Iterator<SearchResultGroup> iter= searchResultGroups.iterator(); iter.hasNext();) { |
| SearchResultGroup group= iter.next(); |
| if (cu.equals(group.getCompilationUnit())) { |
| iter.remove(); |
| return group; |
| } |
| } |
| return null; |
| } |
| |
| private TextEdit createTextChange(SearchMatch searchResult) { |
| return new ReplaceEdit(searchResult.getOffset(), searchResult.getLength(), getNewPackageName()); |
| } |
| |
| private RefactoringStatus analyzeAffectedCompilationUnits() throws CoreException { |
| //TODO: also for both fReferencesTo...; only check each CU once! |
| RefactoringStatus result= new RefactoringStatus(); |
| fOccurrences= Checks.excludeCompilationUnits(fOccurrences, result); |
| if (result.hasFatalError()) |
| return result; |
| |
| result.merge(Checks.checkCompileErrorsInAffectedFiles(fOccurrences)); |
| return result; |
| } |
| |
| /** |
| * @return search scope with |
| * <p>- fPackage and |
| * <p>- all CUs from fOccurrences which are not in a namesake package |
| */ |
| private IJavaSearchScope getPackageAndOccurrencesWithoutNamesakesScope() { |
| List<IJavaElement> scopeList= new ArrayList<>(); |
| scopeList.add(fPackage); |
| for (SearchResultGroup occurrence : fOccurrences) { |
| ICompilationUnit cu= occurrence.getCompilationUnit(); |
| if (cu == null) |
| continue; |
| IPackageFragment pack= (IPackageFragment) cu.getParent(); |
| if (! pack.getElementName().equals(fPackage.getElementName())) |
| scopeList.add(cu); |
| } |
| return SearchEngine.createJavaSearchScope(scopeList.toArray(new IJavaElement[scopeList.size()])); |
| } |
| |
| private List<SearchResultGroup> getReferencesToTypesInNamesakes(IProgressMonitor pm, RefactoringStatus status) throws CoreException { |
| pm.beginTask("", 2); //$NON-NLS-1$ |
| // e.g. renaming B-p.p; project C requires B, X and has ref to B-p.p and X-p.p; |
| // goal: find refs to X-p.p in CUs from fOccurrences |
| |
| // (1) find namesake packages (scope: all packages referenced by CUs in fOccurrences and fPackage) |
| IJavaElement[] elements= new IJavaElement[fOccurrences.length + 1]; |
| for (int i= 0; i < fOccurrences.length; i++) { |
| elements[i]= fOccurrences[i].getCompilationUnit(); |
| } |
| elements[fOccurrences.length]= fPackage; |
| IJavaSearchScope namesakePackagesScope= RefactoringScopeFactory.createReferencedScope(elements); |
| IPackageFragment[] namesakePackages= getNamesakePackages(namesakePackagesScope, new SubProgressMonitor(pm, 1)); |
| if (namesakePackages.length == 0) { |
| pm.done(); |
| return new ArrayList<>(0); |
| } |
| |
| // (2) find refs in fOccurrences and fPackage to namesake packages |
| // (from fOccurrences (without namesakes): may have shared star import) |
| // (from fPackage: may have unimported references to types of namesake packages) |
| IType[] typesToSearch= getTypesInPackages(namesakePackages); |
| if (typesToSearch.length == 0) { |
| pm.done(); |
| return new ArrayList<>(0); |
| } |
| SearchPattern pattern= RefactoringSearchEngine.createOrPattern(typesToSearch, IJavaSearchConstants.REFERENCES); |
| IJavaSearchScope scope= getPackageAndOccurrencesWithoutNamesakesScope(); |
| SearchResultGroup[] results= RefactoringSearchEngine.search(pattern, scope, new SubProgressMonitor(pm, 1), status); |
| pm.done(); |
| return new ArrayList<>(Arrays.asList(results)); |
| } |
| |
| private List<SearchResultGroup> getReferencesToTypesInPackage(IProgressMonitor pm, ReferencesInBinaryContext binaryRefs, RefactoringStatus status) throws CoreException { |
| pm.beginTask("", 2); //$NON-NLS-1$ |
| IJavaSearchScope referencedFromNamesakesScope= RefactoringScopeFactory.create(fPackage, true, false); |
| IPackageFragment[] namesakePackages= getNamesakePackages(referencedFromNamesakesScope, new SubProgressMonitor(pm, 1)); |
| if (namesakePackages.length == 0) { |
| pm.done(); |
| return new ArrayList<>(0); |
| } |
| |
| IJavaSearchScope scope= SearchEngine.createJavaSearchScope(namesakePackages); |
| IType[] typesToSearch= getTypesInPackage(fPackage); |
| if (typesToSearch.length == 0) { |
| pm.done(); |
| return new ArrayList<>(0); |
| } |
| SearchPattern pattern= RefactoringSearchEngine.createOrPattern(typesToSearch, IJavaSearchConstants.REFERENCES); |
| CollectingSearchRequestor requestor= new CuCollectingSearchRequestor(binaryRefs); |
| SearchResultGroup[] results= RefactoringSearchEngine.search(pattern, scope, requestor, new SubProgressMonitor(pm, 1), status); |
| pm.done(); |
| return new ArrayList<>(Arrays.asList(results)); |
| } |
| |
| private IType[] getTypesInPackage(IPackageFragment packageFragment) throws JavaModelException { |
| List<IType> types= new ArrayList<>(); |
| addContainedTypes(packageFragment, types); |
| return types.toArray(new IType[types.size()]); |
| } |
| |
| /** |
| * @param scope search scope |
| * @param pm mrogress monitor |
| * @return all package fragments in <code>scope</code> with same name as <code>fPackage</code>, excluding fPackage |
| * @throws CoreException if search failed |
| */ |
| private IPackageFragment[] getNamesakePackages(IJavaSearchScope scope, IProgressMonitor pm) throws CoreException { |
| SearchPattern pattern= SearchPattern.createPattern(fPackage.getElementName(), IJavaSearchConstants.PACKAGE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE); |
| |
| final HashSet<IPackageFragment> packageFragments= new HashSet<>(); |
| SearchRequestor requestor= new SearchRequestor() { |
| @Override |
| public void acceptSearchMatch(SearchMatch match) throws CoreException { |
| IJavaElement enclosingElement= SearchUtils.getEnclosingJavaElement(match); |
| if (enclosingElement instanceof IPackageFragment) { |
| IPackageFragment pack= (IPackageFragment) enclosingElement; |
| if (! fPackage.equals(pack)) |
| packageFragments.add(pack); |
| } |
| } |
| }; |
| new SearchEngine().search(pattern, SearchUtils.getDefaultSearchParticipants(), scope, requestor, pm); |
| |
| return packageFragments.toArray(new IPackageFragment[packageFragments.size()]); |
| } |
| |
| private IType[] getTypesInPackages(IPackageFragment[] packageFragments) throws JavaModelException { |
| List<IType> types= new ArrayList<>(); |
| for (IPackageFragment pack : packageFragments) { |
| addContainedTypes(pack, types); |
| } |
| return types.toArray(new IType[types.size()]); |
| } |
| |
| private void addContainedTypes(IPackageFragment pack, List<IType> typesCollector) throws JavaModelException { |
| for (IJavaElement child : pack.getChildren()) { |
| if (child instanceof ICompilationUnit) { |
| typesCollector.addAll(Arrays.asList(((ICompilationUnit) child).getTypes())); |
| } else if (child instanceof IOrdinaryClassFile) { |
| typesCollector.add(((IOrdinaryClassFile) child).getType()); |
| } |
| } |
| } |
| |
| private void updateImport(ICompilationUnit cu, IImportDeclaration importDeclaration, String updatedImport) throws JavaModelException { |
| ImportChange importChange= fImportsManager.getImportChange(cu); |
| if (Flags.isStatic(importDeclaration.getFlags())) { |
| importChange.removeStaticImport(importDeclaration.getElementName()); |
| importChange.addStaticImport(Signature.getQualifier(updatedImport), Signature.getSimpleName(updatedImport)); |
| } else { |
| importChange.removeImport(importDeclaration.getElementName()); |
| importChange.addImport(updatedImport); |
| } |
| } |
| |
| /** |
| * Add new imports to types in <code>typeReferences</code> with package <code>fPackage</code>. |
| * @param typeReferences type references |
| * @throws CoreException should not happen |
| */ |
| private void addTypeImports(SearchResultGroup typeReferences) throws CoreException { |
| for (SearchMatch result : typeReferences.getSearchResults()) { |
| IJavaElement enclosingElement= SearchUtils.getEnclosingJavaElement(result); |
| if (! (enclosingElement instanceof IImportDeclaration)) { |
| String reference= getNormalizedTypeReference(result); |
| if (! reference.startsWith(fPackage.getElementName())) { |
| // is unqualified |
| reference= cutOffInnerTypes(reference); |
| ImportChange importChange= fImportsManager.getImportChange(typeReferences.getCompilationUnit()); |
| importChange.addImport(fPackage.getElementName() + '.' + reference); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Add new imports to types in <code>typeReferences</code> with package <code>fNewElementName</code> |
| * and remove old import with <code>fPackage</code>. |
| * @param typeReferences type references |
| * @throws CoreException should not happen |
| */ |
| private void updateTypeImports(SearchResultGroup typeReferences) throws CoreException { |
| for (SearchMatch result : typeReferences.getSearchResults()) { |
| IJavaElement enclosingElement= SearchUtils.getEnclosingJavaElement(result); |
| if (enclosingElement instanceof IImportDeclaration) { |
| IImportDeclaration importDeclaration= (IImportDeclaration) enclosingElement; |
| updateImport(typeReferences.getCompilationUnit(), importDeclaration, getUpdatedImport(importDeclaration)); |
| } else { |
| String reference= getNormalizedTypeReference(result); |
| if (! reference.startsWith(fPackage.getElementName())) { |
| reference= cutOffInnerTypes(reference); |
| ImportChange importChange= fImportsManager.getImportChange(typeReferences.getCompilationUnit()); |
| importChange.removeImport(fPackage.getElementName() + '.' + reference); |
| importChange.addImport(getNewPackageName() + '.' + reference); |
| } // else: already found & updated with package reference search |
| } |
| } |
| } |
| |
| private static String getNormalizedTypeReference(SearchMatch searchResult) throws JavaModelException { |
| ICompilationUnit cu= SearchUtils.getCompilationUnit(searchResult); |
| String reference= cu.getBuffer().getText(searchResult.getOffset(), searchResult.getLength()); |
| //reference may be package-qualified -> normalize (remove comments, etc.): |
| return CommentAnalyzer.normalizeReference(reference); |
| } |
| |
| private static String cutOffInnerTypes(String reference) { |
| int dotPos= reference.indexOf('.'); // cut off inner types |
| if (dotPos != -1) |
| reference= reference.substring(0, dotPos); |
| return reference; |
| } |
| |
| private String getUpdatedImport(IImportDeclaration importDeclaration) { |
| String fullyQualifiedImportType= importDeclaration.getElementName(); |
| int offsetOfDotBeforeTypeName= fPackage.getElementName().length(); |
| String result= getNewPackageName() + fullyQualifiedImportType.substring(offsetOfDotBeforeTypeName); |
| return result; |
| } |
| |
| private String getNewPackageName() { |
| return fProcessor.getNewPackageName(fPackage.getElementName()); |
| } |
| } |
| |
| /** |
| * Collector for import additions/removals. |
| * Saves all changes for a one-pass rewrite. |
| */ |
| static class ImportsManager { |
| public static class ImportChange { |
| private ArrayList<String> fStaticToRemove= new ArrayList<>(); |
| private ArrayList<String[]> fStaticToAdd= new ArrayList<>(); |
| private ArrayList<String> fToRemove= new ArrayList<>(); |
| private ArrayList<String> fToAdd= new ArrayList<>(); |
| |
| public void removeStaticImport(String elementName) { |
| fStaticToRemove.add(elementName); |
| } |
| |
| public void addStaticImport(String declaringType, String memberName) { |
| fStaticToAdd.add(new String[] {declaringType, memberName}); |
| } |
| |
| public void removeImport(String elementName) { |
| fToRemove.add(elementName); |
| } |
| |
| public void addImport(String elementName) { |
| fToAdd.add(elementName); |
| } |
| } |
| |
| private HashMap<ICompilationUnit, ImportChange> fImportChanges= new HashMap<>(); |
| |
| public ImportChange getImportChange(ICompilationUnit cu) { |
| ImportChange importChange= fImportChanges.get(cu); |
| if (importChange == null) { |
| importChange= new ImportChange(); |
| fImportChanges.put(cu, importChange); |
| } |
| return importChange; |
| } |
| |
| public void rewriteImports(TextChangeManager changeManager, IProgressMonitor pm) throws CoreException { |
| for (Entry<ICompilationUnit, ImportChange> entry : fImportChanges.entrySet()) { |
| ICompilationUnit cu= entry.getKey(); |
| ImportChange importChange= entry.getValue(); |
| ImportRewrite importRewrite= StubUtility.createImportRewrite(cu, true); |
| importRewrite.setFilterImplicitImports(false); |
| for (String toRemove : importChange.fStaticToRemove) { |
| importRewrite.removeStaticImport(toRemove); |
| } |
| for (String toRemove : importChange.fToRemove) { |
| importRewrite.removeImport(toRemove); |
| } |
| for (String[] toAdd : importChange.fStaticToAdd) { |
| importRewrite.addStaticImport(toAdd[0], toAdd[1], true); |
| } |
| for (String toAdd : importChange.fToAdd) { |
| importRewrite.addImport(toAdd); |
| } |
| |
| if (importRewrite.hasRecordedChanges()) { |
| TextEdit importEdit= importRewrite.rewriteImports(pm); |
| String name= RefactoringCoreMessages.RenamePackageRefactoring_update_imports; |
| try { |
| TextChangeCompatibility.addTextEdit(changeManager.get(cu), name, importEdit); |
| } catch (MalformedTreeException e) { |
| JavaPlugin.logErrorMessage("MalformedTreeException while processing cu " + cu); //$NON-NLS-1$ |
| throw e; |
| } |
| } |
| } |
| } |
| } |
| |
| private RefactoringStatus initialize(JavaRefactoringArguments extended) { |
| final 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.PACKAGE_FRAGMENT) |
| return JavaRefactoringDescriptorUtil.createInputFatalStatus(element, getProcessorName(), IJavaRefactorings.RENAME_PACKAGE); |
| else |
| fPackage= (IPackageFragment) 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 && !"".equals(name)) //$NON-NLS-1$ |
| setNewElementName(name); |
| else |
| return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME)); |
| final String patterns= extended.getAttribute(ATTRIBUTE_PATTERNS); |
| if (patterns != null && !"".equals(patterns)) //$NON-NLS-1$ |
| fFilePatterns= patterns; |
| else |
| fFilePatterns= ""; //$NON-NLS-1$ |
| final String references= extended.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_REFERENCES); |
| if (references != null) { |
| fUpdateReferences= Boolean.valueOf(references).booleanValue(); |
| } else |
| return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_REFERENCES)); |
| final String matches= extended.getAttribute(ATTRIBUTE_TEXTUAL_MATCHES); |
| if (matches != null) { |
| fUpdateTextualMatches= Boolean.valueOf(matches).booleanValue(); |
| } else |
| return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_TEXTUAL_MATCHES)); |
| final String qualified= extended.getAttribute(ATTRIBUTE_QUALIFIED); |
| if (qualified != null) { |
| fUpdateQualifiedNames= Boolean.valueOf(qualified).booleanValue(); |
| } else |
| return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_QUALIFIED)); |
| final String hierarchical= extended.getAttribute(ATTRIBUTE_HIERARCHICAL); |
| if (hierarchical != null) { |
| fRenameSubpackages= Boolean.valueOf(hierarchical).booleanValue(); |
| } else |
| return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_HIERARCHICAL)); |
| return new RefactoringStatus(); |
| } |
| } |