Skip to content

Commit

Permalink
Model Explorer Move Action should handle multiple file selection
Browse files Browse the repository at this point in the history
* ModelExplorerMoveAction
 * Allow multiple selections

* MoveRefactorAction
 * Although multi-selections are allowed, it is incredibly complex to
   handle all the logic associated with moving resources from different
   directories into the same destintion. Thus, limit the move to only
   moving resources from the same directory.

* MoveRefactoringResources
* RefactorResourcesUtils
 * Multi-selections reveal limitations in the current move refactoring logic
  ** Use a history cache to stop the repeated processing of a resource
     that is related to more than 1 selected resource.
  ** The calculation of import changes needs to know the collection of
     resources being moved since they should be ignored when updating
     any import locations.
  • Loading branch information
Paul Richardson committed Jun 11, 2013
1 parent 6071a10 commit 4f3c718
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,6 @@ private IActionDelegate getMoveActionDelegate() {
@Override
protected boolean updateSelection(IStructuredSelection selection) {
boolean bResult = false;

if ( selection.size() > 1 )
return false;

List lstResourceObjects = SelectionUtilities.getSelectedIResourceObjects( selection );
if ( lstResourceObjects.size() > 0 ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -434,20 +434,29 @@ public static TextFileChange calculateTextChanges(IFile file, Collection<PathPai

/**
* Finds the import locations in the given file and calculates the modified paths against the
* given destination
* given destination. If an import location points to a resource in the given set then nothing
* should be done since that resource is also being moved to the destination and no change
* is necessary.
*
* @param file
* @param destination
* @param file the file to be refactored
* @param destination the location the file is to be refactored to
* @param refactorResources the collection of all resources being refactored
*
* @return a set of path pairs representing the import locations
*
* @throws Exception
*/
public static Set<PathPair> calculateImportChanges(IFile file, String destination) throws Exception {
public static Set<PathPair> calculateImportChanges(IFile file, String destination, Set<IResource> refactorResources) throws Exception {
File nativeFile = file.getRawLocation().makeAbsolute().toFile();
if (nativeFile == null || ! nativeFile.exists())
throw new Exception(getString("ResourcesRefactoring.fileNotFoundError", file.getFullPath())); //$NON-NLS-1$

Set<String> refactorResourcePaths = new HashSet<String>();
for (IResource resource : refactorResources) {
File nativeRes = resource.getRawLocation().makeAbsolute().toFile();
refactorResourcePaths.add(nativeRes.getCanonicalPath());
}

Set<PathPair> importPairs = new HashSet<PathPair>();
File parentFolder = nativeFile.getParentFile();

Expand All @@ -474,6 +483,8 @@ public static Set<PathPair> calculateImportChanges(IFile file, String destinatio
// Find the absolute path of the model location based on the location of the file
File absLocationFile = new File(parentFolder, relativeLocation);
String absLocation = absLocationFile.getCanonicalPath();
if (refactorResourcePaths.contains(absLocation))
continue;

// Use the new proposed location of the file to extrapolate the relative path of the
// import location. This takes advantage of the getRelativePath function by adding
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.util.List;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
Expand Down Expand Up @@ -44,6 +45,25 @@ public void selectionChanged(IAction action, ISelection selection) {
return;
}
}

/*
* Check the resources being moved are in the same directory.
*
* This is a limitation of the move but avoids more difficult
* problems with keeping track of location changes with the
* resources being moved.
*/
IPath parentDirectory = null;
for (IResource resource : resources) {
IPath path = resource.getFullPath();
path = path.uptoSegment(path.segmentCount() - 1);
if (parentDirectory == null) {
parentDirectory = path;
} else if (! parentDirectory.equals(path)) {
action.setEnabled(false);
return;
}
}

super.selectionChanged(action, selection);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ private class RelatedResourceCallback extends VdbResourceCallback {

private final Set<PathPair> pathPairs;

private final Set<IResource> history = new HashSet<IResource>();

/**
* @param pathPairs
*/
Expand All @@ -60,6 +62,28 @@ public void checkValidFile(IFile relatedFile, RefactoringStatus status) {
public void indexFile(IResource resource, IFile relatedFile, RefactoringStatus status) throws Exception {
RefactorResourcesUtils.unloadModelResource(relatedFile);

if (history.contains(relatedFile)) {
/*
* This file has been processed before implying that it is related
* to more than one target resource.
*
* Since pathpairs are global to all resources there is
* no point in processing the related file more than once.
*/
return;
}

// Add the related file to the history to avoid processing it again
history.add(relatedFile);

if (getResourcesAndChildren(status).contains(relatedFile)) {
/*
* Changes are not applicable as the related file is moving
* to the new destination as well
*/
return;
}

IPath relatedFilePath = relatedFile.getRawLocation().makeAbsolute();
IPath relatedParentPath = relatedFilePath.removeLastSegments(1);

Expand Down Expand Up @@ -181,7 +205,7 @@ public RefactoringStatus checkFinalConditions(IProgressMonitor progressMonitor)
// Find the resource's imports as they need to be updated due to the resource move
if (ModelUtil.isModelFile(resource)) {
IFile file = (IFile) resource;
Set<PathPair> importPathPairs = RefactorResourcesUtils.calculateImportChanges(file, destinationPath);
Set<PathPair> importPathPairs = RefactorResourcesUtils.calculateImportChanges(file, destinationPath, getResourcesAndChildren(status));
TextFileChange textFileChange = RefactorResourcesUtils.calculateTextChanges(file, importPathPairs);
if (addTextChange(file, textFileChange)) {
// Calculate the effect on any vdbs containing this modified related file
Expand Down

0 comments on commit 4f3c718

Please sign in to comment.