/**
* Copyright (c) 2005-2013 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Eclipse Public License (EPL).
* Please see the license.txt included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package com.python.pydev.refactoring.refactorer;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.ltk.core.refactoring.participants.RenameRefactoring;
import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation;
import org.python.pydev.core.log.Log;
import org.python.pydev.editor.codecompletion.revisited.visitors.AssignDefinition;
import org.python.pydev.editor.codecompletion.revisited.visitors.Definition;
import org.python.pydev.editor.model.ItemPointer;
import org.python.pydev.editor.refactoring.AbstractPyRefactoring;
import org.python.pydev.editor.refactoring.IPyRefactoring;
import org.python.pydev.editor.refactoring.IPyRefactoringRequest;
import org.python.pydev.editor.refactoring.ModuleRenameRefactoringRequest;
import org.python.pydev.editor.refactoring.MultiModuleMoveRefactoringRequest;
import org.python.pydev.editor.refactoring.PyRefactoringRequest;
import org.python.pydev.editor.refactoring.RefactoringRequest;
import org.python.pydev.editor.refactoring.TooManyMatchesException;
import org.python.pydev.parser.visitors.scope.ASTEntry;
import org.python.pydev.shared_core.structure.Tuple;
import org.python.pydev.shared_ui.EditorUtils;
import com.python.pydev.refactoring.IPyRefactoring2;
import com.python.pydev.refactoring.wizards.RefactorProcessFactory;
import com.python.pydev.refactoring.wizards.rename.PyReferenceSearcher;
import com.python.pydev.refactoring.wizards.rename.PyRenameEntryPoint;
import com.python.pydev.refactoring.wizards.rename.PyRenameRefactoringWizard;
import com.python.pydev.ui.hierarchy.HierarchyNodeModel;
/**
* This is the entry point for any refactoring that we implement.
*
* @author Fabio
*/
public class Refactorer extends AbstractPyRefactoring implements IPyRefactoring2 {
@Override
public String getName() {
return "PyDev Extensions Refactorer";
}
/**
* Renames something...
*
* Basically passes things to the rename processor (it will choose the kind of rename that will happen).
*
* @see org.python.pydev.editor.refactoring.IPyRefactoring#rename(org.python.pydev.editor.refactoring.RefactoringRequest)
*/
@Override
public String rename(IPyRefactoringRequest request) {
try {
List<RefactoringRequest> actualRequests = request.getRequests();
if (actualRequests.size() == 1) {
RefactoringRequest req = actualRequests.get(0);
//Note: if it's already a ModuleRenameRefactoringRequest, no need to change anything.
if (!(req.isModuleRenameRefactoringRequest())) {
//Note: if we're renaming an import, we must change to the appropriate req
IPyRefactoring pyRefactoring = AbstractPyRefactoring.getPyRefactoring();
ItemPointer[] pointers = pyRefactoring.findDefinition(req);
for (ItemPointer pointer : pointers) {
Definition definition = pointer.definition;
if (RefactorProcessFactory.isModuleRename(definition)) {
try {
request = new PyRefactoringRequest(new ModuleRenameRefactoringRequest(
definition.module.getFile(), req.nature, null));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
PyRenameEntryPoint entryPoint = new PyRenameEntryPoint(request);
RenameRefactoring renameRefactoring = new RenameRefactoring(entryPoint);
request.fillInitialNameAndOffset();
String title = "Rename";
if (request instanceof MultiModuleMoveRefactoringRequest) {
MultiModuleMoveRefactoringRequest multiModuleMoveRefactoringRequest = (MultiModuleMoveRefactoringRequest) request;
title = "Move To package (project: "
+ multiModuleMoveRefactoringRequest.getTarget().getProject().getName()
+ ")";
}
final PyRenameRefactoringWizard wizard = new PyRenameRefactoringWizard(renameRefactoring, title,
"inputPageDescription", request);
try {
RefactoringWizardOpenOperation op = new RefactoringWizardOpenOperation(wizard);
op.run(EditorUtils.getShell(), "Rename Refactor Action");
} catch (InterruptedException e) {
// do nothing. User action got cancelled
}
} catch (Exception e) {
Log.log(e);
}
return null;
}
@Override
public ItemPointer[] findDefinition(RefactoringRequest request)
throws TooManyMatchesException, BadLocationException {
return new RefactorerFindDefinition().findDefinition(request);
}
// --------------------------------------------------------- IPyRefactoring2
@Override
public boolean areAllInSameClassHierarchy(List<AssignDefinition> defs) {
return new RefactorerFinds(this).areAllInSameClassHierarchy(defs);
}
@Override
public HierarchyNodeModel findClassHierarchy(RefactoringRequest request, boolean findOnlyParents) {
return new RefactorerFinds(this).findClassHierarchy(request, findOnlyParents);
}
@Override
public Map<Tuple<String, File>, HashSet<ASTEntry>> findAllOccurrences(RefactoringRequest req)
throws OperationCanceledException, CoreException {
PyReferenceSearcher pyReferenceSearcher = new PyReferenceSearcher(req);
//to see if a new request was not created in the meantime (in which case this one will be cancelled)
req.checkCancelled();
IProgressMonitor monitor = req.getMonitor();
Map<Tuple<String, File>, HashSet<ASTEntry>> occurrencesInOtherFiles;
try {
monitor.beginTask("Find all occurrences", 100);
monitor.setTaskName("Find all occurrences");
try {
req.pushMonitor(new SubProgressMonitor(monitor, 10));
pyReferenceSearcher.prepareSearch(req);
} catch (PyReferenceSearcher.SearchException | BadLocationException e) {
return null;
} finally {
req.popMonitor().done();
}
req.checkCancelled();
try {
req.pushMonitor(new SubProgressMonitor(monitor, 85));
pyReferenceSearcher.search(req);
} catch (PyReferenceSearcher.SearchException e) {
return null;
} finally {
req.popMonitor().done();
}
req.checkCancelled();
occurrencesInOtherFiles = pyReferenceSearcher.getWorkspaceReferences(req);
HashSet<ASTEntry> occurrences = pyReferenceSearcher.getLocalReferences(req);
occurrencesInOtherFiles.put(new Tuple<String, File>(req.moduleName, req.pyEdit.getEditorFile()),
occurrences);
req.getMonitor().worked(5);
} finally {
monitor.done();
}
return occurrencesInOtherFiles;
}
}