| /******************************************************************************* |
| * Copyright (c) 2000, 2017 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 |
| * |
| *******************************************************************************/ |
| package org.eclipse.dltk.internal.corext.refactoring.reorg; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Set; |
| |
| import org.eclipse.core.filebuffers.FileBuffers; |
| import org.eclipse.core.filebuffers.ITextFileBuffer; |
| import org.eclipse.core.filebuffers.LocationKind; |
| import org.eclipse.core.resources.IContainer; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IFolder; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IResourceVisitor; |
| import org.eclipse.core.resources.mapping.IResourceChangeDescriptionFactory; |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.OperationCanceledException; |
| import org.eclipse.dltk.core.DLTKCore; |
| import org.eclipse.dltk.core.DLTKFeatures; |
| import org.eclipse.dltk.core.DLTKLanguageManager; |
| import org.eclipse.dltk.core.IDLTKLanguageToolkit; |
| import org.eclipse.dltk.core.IModelElement; |
| import org.eclipse.dltk.core.IProjectFragment; |
| import org.eclipse.dltk.core.IScriptFolder; |
| import org.eclipse.dltk.core.IScriptProject; |
| import org.eclipse.dltk.core.ISourceModule; |
| import org.eclipse.dltk.core.IType; |
| import org.eclipse.dltk.core.ModelException; |
| import org.eclipse.dltk.internal.corext.refactoring.RefactoringAvailabilityTester; |
| import org.eclipse.dltk.internal.corext.refactoring.RefactoringCoreMessages; |
| import org.eclipse.dltk.internal.corext.refactoring.participants.ResourceProcessors; |
| import org.eclipse.dltk.internal.corext.refactoring.participants.ScriptProcessors; |
| import org.eclipse.dltk.internal.corext.refactoring.tagging.ICommentProvider; |
| import org.eclipse.dltk.internal.corext.refactoring.util.ModelElementUtil; |
| import org.eclipse.dltk.internal.corext.refactoring.util.ResourceUtil; |
| import org.eclipse.dltk.internal.corext.refactoring.util.TextChangeManager; |
| import org.eclipse.dltk.internal.corext.util.Messages; |
| import org.eclipse.dltk.internal.corext.util.Resources; |
| import org.eclipse.dltk.ui.DLTKUIPlugin; |
| import org.eclipse.ltk.core.refactoring.Change; |
| import org.eclipse.ltk.core.refactoring.RefactoringStatus; |
| import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; |
| import org.eclipse.ltk.core.refactoring.participants.DeleteProcessor; |
| import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant; |
| import org.eclipse.ltk.core.refactoring.participants.ResourceChangeChecker; |
| import org.eclipse.ltk.core.refactoring.participants.SharableParticipants; |
| |
| public final class ScriptDeleteProcessor extends DeleteProcessor |
| implements ICommentProvider { |
| |
| private boolean fWasCanceled; |
| private Object[] fElements; |
| private IResource[] fResources; |
| private IModelElement[] fScriptElements; |
| private IReorgQueries fDeleteQueries; |
| private DeleteModifications fDeleteModifications; |
| private String fComment; |
| |
| private Change fDeleteChange; |
| private boolean fDeleteSubPackages; |
| |
| public static final String IDENTIFIER = "org.eclipse.dltk.ui.DeleteProcessor"; //$NON-NLS-1$ |
| |
| public ScriptDeleteProcessor(Object[] elements) { |
| fElements = elements; |
| fResources = RefactoringAvailabilityTester.getResources(elements); |
| fScriptElements = RefactoringAvailabilityTester |
| .getScriptElements(elements); |
| fDeleteSubPackages = false; |
| fWasCanceled = false; |
| } |
| |
| // ---- IRefactoringProcessor |
| // --------------------------------------------------- |
| |
| @Override |
| public String getIdentifier() { |
| return IDENTIFIER; |
| } |
| |
| @Override |
| public boolean isApplicable() throws CoreException { |
| if (fElements.length == 0) |
| return false; |
| if (fElements.length != fResources.length + fScriptElements.length) |
| return false; |
| for (int i = 0; i < fResources.length; i++) { |
| if (!RefactoringAvailabilityTester.isDeleteAvailable(fResources[i])) |
| return false; |
| } |
| for (int i = 0; i < fScriptElements.length; i++) { |
| if (!RefactoringAvailabilityTester |
| .isDeleteAvailable(fScriptElements[i])) |
| return false; |
| } |
| return true; |
| } |
| |
| public boolean needsProgressMonitor() { |
| if (fResources != null && fResources.length > 0) |
| return true; |
| if (fScriptElements != null) { |
| for (int i = 0; i < fScriptElements.length; i++) { |
| int type = fScriptElements[i].getElementType(); |
| if (type <= IModelElement.SOURCE_MODULE) |
| return true; |
| } |
| } |
| return false; |
| |
| } |
| |
| @Override |
| public String getProcessorName() { |
| return RefactoringCoreMessages.DeleteRefactoring_7; |
| } |
| |
| @Override |
| public Object[] getElements() { |
| return fElements; |
| } |
| |
| @Override |
| public RefactoringParticipant[] loadParticipants(RefactoringStatus status, |
| SharableParticipants shared) throws CoreException { |
| return fDeleteModifications.loadParticipants(status, this, |
| getAffectedProjectNatures(), shared); |
| } |
| |
| private String[] getAffectedProjectNatures() throws CoreException { |
| String[] jNatures = ScriptProcessors |
| .computeAffectedNaturs(fScriptElements); |
| String[] rNatures = ResourceProcessors |
| .computeAffectedNatures(fResources); |
| Set<String> result = new HashSet<>(); |
| result.addAll(Arrays.asList(jNatures)); |
| result.addAll(Arrays.asList(rNatures)); |
| return result.toArray(new String[result.size()]); |
| } |
| |
| public void setDeleteSubPackages(boolean selection) { |
| fDeleteSubPackages = selection; |
| } |
| |
| public boolean getDeleteSubPackages() { |
| return fDeleteSubPackages; |
| } |
| |
| public boolean hasSubPackagesToDelete() { |
| try { |
| for (int i = 0; i < fScriptElements.length; i++) { |
| if (fScriptElements[i] instanceof IScriptFolder) { |
| IScriptFolder scriptFolder = (IScriptFolder) fScriptElements[i]; |
| if (scriptFolder.isRootFolder()) |
| continue; // see bug 132576 (can remove this if(..) |
| // continue; statement when bug is fixed) |
| if (scriptFolder.hasSubfolders()) |
| return true; |
| } |
| } |
| } catch (ModelException e) { |
| DLTKUIPlugin.log(e); |
| } |
| return false; |
| } |
| |
| public void setQueries(IReorgQueries queries) { |
| Assert.isNotNull(queries); |
| fDeleteQueries = queries; |
| } |
| |
| public IModelElement[] getScriptElementsToDelete() { |
| return fScriptElements; |
| } |
| |
| public boolean wasCanceled() { |
| return fWasCanceled; |
| } |
| |
| public IResource[] getResourcesToDelete() { |
| return fResources; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.dltk.internal.corext.refactoring.base.Refactoring# |
| * checkActivation(org.eclipse.core.runtime.IProgressMonitor) |
| */ |
| @Override |
| public RefactoringStatus checkInitialConditions(IProgressMonitor pm) |
| throws CoreException { |
| Assert.isNotNull(fDeleteQueries);// must be set before checking |
| // activation |
| RefactoringStatus result = new RefactoringStatus(); |
| result.merge(RefactoringStatus.create( |
| Resources.checkInSync(ReorgUtils.getNotLinked(fResources)))); |
| IResource[] javaResources = ReorgUtils.getResources(fScriptElements); |
| result.merge(RefactoringStatus.create( |
| Resources.checkInSync(ReorgUtils.getNotLinked(javaResources)))); |
| for (int i = 0; i < fScriptElements.length; i++) { |
| // IModelElement element= fScriptElements[i]; |
| // if (element instanceof IType && ((IType)element).isAnonymous()) { |
| // // work around for bug |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=44450 |
| // // result.addFatalError("Currently, there isn't any support to |
| // delete an anonymous type."); |
| // } |
| } |
| return result; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.dltk.internal.corext.refactoring.base.Refactoring#checkInput( |
| * org.eclipse.core.runtime.IProgressMonitor) |
| */ |
| @Override |
| public RefactoringStatus checkFinalConditions(IProgressMonitor pm, |
| CheckConditionsContext context) throws CoreException { |
| pm.beginTask(RefactoringCoreMessages.DeleteRefactoring_1, 1); |
| try { |
| fWasCanceled = false; |
| RefactoringStatus result = new RefactoringStatus(); |
| |
| recalculateElementsToDelete(); |
| |
| TextChangeManager manager = new TextChangeManager(); |
| fDeleteChange = DeleteChangeCreator.createDeleteChange(manager, |
| fResources, fScriptElements, getProcessorName()); |
| checkDirtySourceModules(result); |
| checkDirtyResources(result); |
| fDeleteModifications = new DeleteModifications(); |
| fDeleteModifications.delete(fResources); |
| fDeleteModifications.delete(fScriptElements); |
| fDeleteModifications.postProcess(); |
| |
| ResourceChangeChecker checker = context |
| .getChecker(ResourceChangeChecker.class); |
| IResourceChangeDescriptionFactory deltaFactory = checker |
| .getDeltaFactory(); |
| fDeleteModifications.buildDelta(deltaFactory); |
| IFile[] files = getBuildpathFiles(); |
| for (int i = 0; i < files.length; i++) { |
| deltaFactory.change(files[i]); |
| } |
| files = ResourceUtil.getFiles(manager.getAllSourceModules()); |
| for (int i = 0; i < files.length; i++) { |
| deltaFactory.change(files[i]); |
| } |
| return result; |
| } catch (OperationCanceledException e) { |
| fWasCanceled = true; |
| throw e; |
| } catch (ModelException e) { |
| throw e; |
| } catch (CoreException e) { |
| throw new ModelException(e); |
| } finally { |
| pm.done(); |
| } |
| } |
| |
| private void checkDirtySourceModules(RefactoringStatus result) |
| throws CoreException { |
| if (fScriptElements == null || fScriptElements.length == 0) |
| return; |
| for (int je = 0; je < fScriptElements.length; je++) { |
| IModelElement element = fScriptElements[je]; |
| if (element instanceof ISourceModule) { |
| checkDirtySourceModule(result, (ISourceModule) element); |
| } else if (element instanceof IScriptFolder) { |
| ISourceModule[] units = ((IScriptFolder) element) |
| .getSourceModules(); |
| for (int u = 0; u < units.length; u++) { |
| checkDirtySourceModule(result, units[u]); |
| } |
| } |
| } |
| } |
| |
| private void checkDirtySourceModule(RefactoringStatus result, |
| ISourceModule cunit) { |
| IResource resource = cunit.getResource(); |
| if (resource == null || resource.getType() != IResource.FILE) |
| return; |
| checkDirtyFile(result, (IFile) resource); |
| } |
| |
| private void checkDirtyResources(final RefactoringStatus result) |
| throws CoreException { |
| for (int i = 0; i < fResources.length; i++) { |
| IResource resource = fResources[i]; |
| resource.accept((IResourceVisitor) visitedResource -> { |
| if (visitedResource instanceof IFile) { |
| checkDirtyFile(result, (IFile) visitedResource); |
| } |
| return true; |
| }, IResource.DEPTH_INFINITE, false); |
| } |
| } |
| |
| private void checkDirtyFile(RefactoringStatus result, IFile file) { |
| if (file == null || !file.exists()) |
| return; |
| ITextFileBuffer buffer = FileBuffers.getTextFileBufferManager() |
| .getTextFileBuffer(file.getFullPath(), LocationKind.NORMALIZE); |
| if (buffer != null && buffer.isDirty()) { |
| if (buffer.isStateValidated() && buffer.isSynchronized()) { |
| result.addWarning(Messages.format( |
| RefactoringCoreMessages.ScriptDeleteProcessor_unsaved_changes, |
| file.getFullPath().toString())); |
| } else { |
| result.addFatalError(Messages.format( |
| RefactoringCoreMessages.ScriptDeleteProcessor_unsaved_changes, |
| file.getFullPath().toString())); |
| } |
| } |
| } |
| |
| /* |
| * The set of elements that will eventually be deleted may be very different |
| * from the set originally selected - there may be fewer, more or different |
| * elements. This method is used to calculate the set of elements that will |
| * be deleted - if necessary, it asks the user. |
| */ |
| private void recalculateElementsToDelete() throws CoreException { |
| // the sequence is critical here |
| |
| if (fDeleteSubPackages) /* |
| * add subpackages first, to allow removing |
| * elements with parents in selection etc. |
| */ |
| addSubPackages(); |
| |
| removeElementsWithParentsInSelection(); /* |
| * ask before adding empty cus - |
| * you don't want to ask if you, |
| * for example delete the |
| * package, in which the cus |
| * live |
| */ |
| removeUnconfirmedFoldersThatContainSourceFolders(); /* |
| * a selected folder |
| * may be a parent |
| * of a source |
| * folder we must |
| * inform the user |
| * about it and ask |
| * if ok to delete |
| * the folder |
| */ |
| removeUnconfirmedReferencedArchives(); |
| addEmptySourceModulesToDelete(); |
| removeScriptElementsChildrenOfScriptElements();/* |
| * because adding cus |
| * may create elements |
| * (types in cus) whose |
| * parents are in |
| * selection |
| */ |
| confirmDeletingReadOnly(); /* |
| * after empty cus - you want to ask for all |
| * cus that are to be deleted |
| */ |
| |
| addDeletableParentPackagesOnPackageDeletion(); /* |
| * do not change the |
| * sequence in |
| * fScriptElements after |
| * this method |
| */ |
| } |
| |
| /** |
| * Adds all subpackages of the selected packages to the list of items to be |
| * deleted. |
| * |
| * @throws ModelException |
| */ |
| private void addSubPackages() throws ModelException { |
| |
| final Set<IModelElement> modelElements = new HashSet<>(); |
| for (int i = 0; i < fScriptElements.length; i++) { |
| if (fScriptElements[i] instanceof IScriptFolder) { |
| modelElements.addAll( |
| Arrays.asList(ModelElementUtil.getPackageAndSubpackages( |
| (IScriptFolder) fScriptElements[i]))); |
| } else { |
| modelElements.add(fScriptElements[i]); |
| } |
| } |
| |
| fScriptElements = modelElements |
| .toArray(new IModelElement[modelElements.size()]); |
| } |
| |
| /** |
| * Add deletable parent packages to the list of items to delete. |
| * |
| * @throws CoreException |
| */ |
| private void addDeletableParentPackagesOnPackageDeletion() |
| throws CoreException { |
| |
| final List/* <IScriptFolder */ initialPackagesToDelete = ReorgUtils |
| .getElementsOfType(fScriptElements, |
| IModelElement.SCRIPT_FOLDER); |
| |
| if (initialPackagesToDelete.size() == 0) |
| return; |
| |
| // Move from inner to outer packages |
| Collections.sort(initialPackagesToDelete, (arg0, arg1) -> { |
| IScriptFolder one = (IScriptFolder) arg0; |
| IScriptFolder two = (IScriptFolder) arg1; |
| return two.getElementName().compareTo(one.getElementName()); |
| }); |
| |
| // Get resources andscriptelements which will be deleted as well |
| final Set/* <IResource> */ deletedChildren = new HashSet(); |
| deletedChildren.addAll(Arrays.asList(fResources)); |
| for (int i = 0; i < fScriptElements.length; i++) { |
| if (!ReorgUtils.isInsideSourceModule(fScriptElements[i])) |
| deletedChildren.add(fScriptElements[i].getResource()); |
| } |
| |
| // new package list in the right sequence |
| final List<IScriptFolder> allFragmentsToDelete = new ArrayList<>(); |
| |
| for (Iterator outerIter = initialPackagesToDelete.iterator(); outerIter |
| .hasNext();) { |
| final IScriptFolder currentScriptFolder = (IScriptFolder) outerIter |
| .next(); |
| |
| // The package will at least be cleared |
| allFragmentsToDelete.add(currentScriptFolder); |
| |
| if (canRemoveCompletely(currentScriptFolder, |
| initialPackagesToDelete)) { |
| |
| final IScriptFolder parent = ModelElementUtil |
| .getParentSubpackage(currentScriptFolder); |
| if (parent != null |
| && !initialPackagesToDelete.contains(parent)) { |
| |
| final List/* <IScriptFolder> */ emptyParents = new ArrayList(); |
| addDeletableParentPackages(parent, initialPackagesToDelete, |
| deletedChildren, emptyParents); |
| |
| // Add parents in the right sequence (inner to outer) |
| allFragmentsToDelete.addAll(emptyParents); |
| } |
| } |
| } |
| |
| // Remove resources in deleted packages; and the packages as well |
| final List<IModelElement> modelElements = new ArrayList<>(); |
| for (int i = 0; i < fScriptElements.length; i++) { |
| if (!(fScriptElements[i] instanceof IScriptFolder)) { |
| // remove children of deleted packages |
| final IScriptFolder frag = (IScriptFolder) fScriptElements[i] |
| .getAncestor(IModelElement.SCRIPT_FOLDER); |
| if (!allFragmentsToDelete.contains(frag)) |
| modelElements.add(fScriptElements[i]); |
| } |
| } |
| // Re-add deleted packages - note the (new) sequence |
| modelElements.addAll(allFragmentsToDelete); |
| |
| // Remove resources in deleted folders |
| final List<IResource> resources = new ArrayList<>(); |
| for (int i = 0; i < fResources.length; i++) { |
| IResource parent = fResources[i]; |
| if (parent.getType() == IResource.FILE) |
| parent = parent.getParent(); |
| if (!deletedChildren.contains(parent)) |
| resources.add(fResources[i]); |
| } |
| |
| fScriptElements = modelElements |
| .toArray(new IModelElement[modelElements.size()]); |
| fResources = resources.toArray(new IResource[resources.size()]); |
| } |
| |
| /** |
| * Returns true if this initially selected package is really deletable (if |
| * it has non-selected subpackages, it may only be cleared). |
| * |
| */ |
| private boolean canRemoveCompletely(IScriptFolder pack, |
| List packagesToDelete) throws ModelException { |
| final IScriptFolder[] subPackages = ModelElementUtil |
| .getPackageAndSubpackages(pack); |
| for (int i = 0; i < subPackages.length; i++) { |
| if (!(subPackages[i].equals(pack)) |
| && !(packagesToDelete.contains(subPackages[i]))) |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Adds deletable parent packages of the fragment "frag" to the list |
| * "deletableParentPackages"; also adds the resources of those packages to |
| * the set "resourcesToDelete". |
| * |
| */ |
| private void addDeletableParentPackages(IScriptFolder frag, |
| List initialPackagesToDelete, Set resourcesToDelete, |
| List deletableParentPackages) throws CoreException { |
| |
| if (frag.getResource().isLinked()) { |
| final IConfirmQuery query = fDeleteQueries.createYesNoQuery( |
| RefactoringCoreMessages.ScriptDeleteProcessor_confirm_linked_folder_delete, |
| false, IReorgQueries.CONFIRM_DELETE_LINKED_PARENT); |
| if (!query.confirm(Messages.format( |
| RefactoringCoreMessages.ScriptDeleteProcessor_delete_linked_folder_question, |
| new String[] { frag.getResource().getName() }))) |
| return; |
| } |
| |
| final IResource[] children = (((IContainer) frag.getResource())) |
| .members(); |
| for (int i = 0; i < children.length; i++) { |
| // Child must be a package fragment already in the list, |
| // or a resource which is deleted as well. |
| if (!resourcesToDelete.contains(children[i])) |
| return; |
| } |
| resourcesToDelete.add(frag.getResource()); |
| deletableParentPackages.add(frag); |
| |
| final IScriptFolder parent = ModelElementUtil.getParentSubpackage(frag); |
| if (parent != null && !initialPackagesToDelete.contains(parent)) |
| addDeletableParentPackages(parent, initialPackagesToDelete, |
| resourcesToDelete, deletableParentPackages); |
| } |
| |
| // ask for confirmation of deletion of all package fragment roots that are |
| // on buildpaths of other projects |
| private void removeUnconfirmedReferencedArchives() throws ModelException { |
| String queryTitle = RefactoringCoreMessages.DeleteRefactoring_2; |
| IConfirmQuery query = fDeleteQueries.createYesYesToAllNoNoToAllQuery( |
| queryTitle, true, |
| IReorgQueries.CONFIRM_DELETE_REFERENCED_ARCHIVES); |
| removeUnconfirmedReferencedProjectFragments(query); |
| removeUnconfirmedReferencedArchiveFiles(query); |
| } |
| |
| private void removeUnconfirmedReferencedArchiveFiles(IConfirmQuery query) |
| throws ModelException, OperationCanceledException { |
| List<IFile> filesToSkip = new ArrayList<>(0); |
| for (int i = 0; i < fResources.length; i++) { |
| IResource resource = fResources[i]; |
| if (!(resource instanceof IFile)) |
| continue; |
| |
| IScriptProject project = DLTKCore.create(resource.getProject()); |
| if (project == null || !project.exists()) |
| continue; |
| IProjectFragment root = project |
| .findProjectFragment(resource.getFullPath()); |
| if (root == null) |
| continue; |
| List referencingProjects = new ArrayList(1); |
| referencingProjects.add(root.getScriptProject()); |
| referencingProjects.addAll(Arrays |
| .asList(ModelElementUtil.getReferencingProjects(root))); |
| if (skipDeletingReferencedRoot(query, root, referencingProjects)) |
| filesToSkip.add((IFile) resource); |
| } |
| removeFromSetToDelete( |
| filesToSkip.toArray(new IFile[filesToSkip.size()])); |
| } |
| |
| private void removeUnconfirmedReferencedProjectFragments( |
| IConfirmQuery query) |
| throws ModelException, OperationCanceledException { |
| List<IModelElement> rootsToSkip = new ArrayList<>(0); |
| for (int i = 0; i < fScriptElements.length; i++) { |
| IModelElement element = fScriptElements[i]; |
| if (!(element instanceof IProjectFragment)) |
| continue; |
| IProjectFragment root = (IProjectFragment) element; |
| List referencingProjects = Arrays |
| .asList(ModelElementUtil.getReferencingProjects(root)); |
| if (skipDeletingReferencedRoot(query, root, referencingProjects)) |
| rootsToSkip.add(root); |
| } |
| removeFromSetToDelete( |
| rootsToSkip.toArray(new IModelElement[rootsToSkip.size()])); |
| } |
| |
| private static boolean skipDeletingReferencedRoot(IConfirmQuery query, |
| IProjectFragment root, List referencingProjects) |
| throws OperationCanceledException { |
| if (referencingProjects.isEmpty() || root == null || !root.exists() |
| || !root.isArchive()) |
| return false; |
| String question = Messages.format( |
| RefactoringCoreMessages.DeleteRefactoring_3, |
| root.getElementName()); |
| return !query.confirm(question, referencingProjects.toArray()); |
| } |
| |
| private void removeUnconfirmedFoldersThatContainSourceFolders() |
| throws CoreException { |
| String queryTitle = RefactoringCoreMessages.DeleteRefactoring_4; |
| IConfirmQuery query = fDeleteQueries.createYesYesToAllNoNoToAllQuery( |
| queryTitle, true, |
| IReorgQueries.CONFIRM_DELETE_FOLDERS_CONTAINING_SOURCE_FOLDERS); |
| List<IResource> foldersToSkip = new ArrayList<>(0); |
| for (int i = 0; i < fResources.length; i++) { |
| IResource resource = fResources[i]; |
| if (resource instanceof IFolder) { |
| IFolder folder = (IFolder) resource; |
| if (containsSourceFolder(folder)) { |
| String question = Messages.format( |
| RefactoringCoreMessages.DeleteRefactoring_5, |
| folder.getName()); |
| if (!query.confirm(question)) |
| foldersToSkip.add(folder); |
| } |
| } |
| } |
| removeFromSetToDelete( |
| foldersToSkip.toArray(new IResource[foldersToSkip.size()])); |
| } |
| |
| private static boolean containsSourceFolder(IFolder folder) |
| throws CoreException { |
| IResource[] subFolders = folder.members(); |
| for (int i = 0; i < subFolders.length; i++) { |
| if (!(subFolders[i] instanceof IFolder)) |
| continue; |
| IModelElement element = DLTKCore.create(folder); |
| if (element instanceof IProjectFragment) |
| return true; |
| if (element instanceof IScriptFolder) |
| continue; |
| if (containsSourceFolder((IFolder) subFolders[i])) |
| return true; |
| } |
| return false; |
| } |
| |
| private void removeElementsWithParentsInSelection() { |
| ParentChecker parentUtil = new ParentChecker(fResources, |
| fScriptElements); |
| parentUtil.removeElementsWithAncestorsOnList(false); |
| fScriptElements = parentUtil.getScriptElements(); |
| fResources = parentUtil.getResources(); |
| } |
| |
| private void removeScriptElementsChildrenOfScriptElements() { |
| ParentChecker parentUtil = new ParentChecker(fResources, |
| fScriptElements); |
| parentUtil.removeElementsWithAncestorsOnList(true); |
| fScriptElements = parentUtil.getScriptElements(); |
| } |
| |
| private IFile[] getBuildpathFiles() { |
| List result = new ArrayList(); |
| for (int i = 0; i < fScriptElements.length; i++) { |
| IModelElement element = fScriptElements[i]; |
| if (element instanceof IProjectFragment) { |
| IProject project = element.getScriptProject().getProject(); |
| IFile buildpathFile = project.getFile(".classpath"); //$NON-NLS-1$ |
| if (buildpathFile.exists()) |
| result.add(buildpathFile); |
| } |
| } |
| return (IFile[]) result.toArray(new IFile[result.size()]); |
| } |
| |
| @Override |
| public Change createChange(IProgressMonitor pm) throws CoreException { |
| pm.beginTask("", 1); //$NON-NLS-1$ |
| pm.done(); |
| return fDeleteChange; |
| } |
| |
| private void addToSetToDelete(IModelElement[] newElements) { |
| fScriptElements = ReorgUtils.union(fScriptElements, newElements); |
| } |
| |
| private void removeFromSetToDelete(IResource[] resourcesToNotDelete) { |
| fResources = ReorgUtils.setMinus(fResources, resourcesToNotDelete); |
| } |
| |
| private void removeFromSetToDelete(IModelElement[] elementsToNotDelete) { |
| fScriptElements = ReorgUtils.setMinus(fScriptElements, |
| elementsToNotDelete); |
| } |
| |
| // private static IField[] getFields(IModelElement[] elements){ |
| // List fields= new ArrayList(3); |
| // for (int i= 0; i < elements.length; i++) { |
| // if (elements[i] instanceof IField) |
| // fields.add(elements[i]); |
| // } |
| // return (IField[]) fields.toArray(new IField[fields.size()]); |
| // } |
| |
| // ----------- read-only confirmation business ------ |
| private void confirmDeletingReadOnly() throws CoreException { |
| if (!ReadOnlyResourceFinder.confirmDeleteOfReadOnlyElements( |
| fScriptElements, fResources, fDeleteQueries)) |
| throw new OperationCanceledException(); // saying 'no' to this one |
| // is like cancelling the |
| // whole operation |
| } |
| |
| // ----------- empty source modules related method |
| private void addEmptySourceModulesToDelete() throws ModelException { |
| Set<ISourceModule> modulesToEmpty = getCusToEmpty(); |
| addToSetToDelete(modulesToEmpty |
| .toArray(new ISourceModule[modulesToEmpty.size()])); |
| } |
| |
| private Set<ISourceModule> getCusToEmpty() throws ModelException { |
| Set<ISourceModule> result = new HashSet<>(); |
| for (int i = 0; i < fScriptElements.length; i++) { |
| IModelElement element = fScriptElements[i]; |
| ISourceModule module = ReorgUtils.getSourceModule(element); |
| if (module != null && !result.contains(module)) { |
| IDLTKLanguageToolkit toolkit = DLTKLanguageManager |
| .getLanguageToolkit(module); |
| if (toolkit != null && toolkit |
| .get(DLTKFeatures.DELETE_MODULE_WITHOUT_TOP_LEVEL_TYPES) |
| && willHaveAllTopLevelTypesDeleted(module)) { |
| result.add(module); |
| } |
| } |
| } |
| return result; |
| } |
| |
| private boolean willHaveAllTopLevelTypesDeleted(ISourceModule cu) |
| throws ModelException { |
| Set elementSet = new HashSet(Arrays.asList(fScriptElements)); |
| IType[] topLevelTypes = cu.getTypes(); |
| for (int i = 0; i < topLevelTypes.length; i++) { |
| if (!elementSet.contains(topLevelTypes[i])) |
| return false; |
| } |
| return true; |
| } |
| |
| @Override |
| public boolean canEnableComment() { |
| return true; |
| } |
| |
| @Override |
| public String getComment() { |
| return fComment; |
| } |
| |
| @Override |
| public void setComment(String comment) { |
| fComment = comment; |
| } |
| } |