package jetbrains.mps.idea.core.refactoring;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.refactoring.rename.RenameHandler;
import jetbrains.mps.ide.actions.MPSCommonDataKeys;
import jetbrains.mps.project.MPSProject;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.mps.openapi.model.SNode;
import org.jetbrains.mps.openapi.model.SNodeUtil;
import org.jetbrains.mps.openapi.module.ModelAccess;
import org.jetbrains.mps.openapi.module.SRepository;
/**
* danilla 5/29/13
*/
// This is glue that will invoke MPS refactoring, when Idea refactoring action is invoked
public class MPSRenameRefactoringHandler implements RenameHandler {
private static final Logger LOG = Logger.getInstance("#jetbrains.mps.idea.core.refactoring.MPSRenameRefactoringHandler");
@Override
public boolean isAvailableOnDataContext(DataContext dataContext) {
SNode currentNode = MPSCommonDataKeys.NODE.getData(dataContext);
return currentNode != null;
}
@Override
public boolean isRenaming(DataContext dataContext) {
return isAvailableOnDataContext(dataContext);
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) {
LOG.assertTrue(false);
}
@Override
public void invoke(@NotNull final Project project, @NotNull PsiElement[] elements, final DataContext dataContext) {
// we ignore 'elements' and take current node from dataContext
// because Idea takes the root node as the element for our editor
final MPSProject mpsProject = project.getComponent(MPSProject.class);
final SRepository repository = mpsProject.getRepository();
ModelAccess modelAccess = repository.getModelAccess();
// taking NODE from dataContext outside of readInEDT because we can't take anything
// from dataContext after we've invoked something in EDT;
// see DataManagerImpl.getData() LOG.error() cannot share data context ...
// also see IdeKeyEventDispatcher.processAction() for place where initial event count is set
final SNode node = MPSCommonDataKeys.NODE.getData(dataContext);
modelAccess.runReadInEDT(new Runnable() {
@Override
public void run() {
if (!SNodeUtil.isAccessible(node, repository)) {
return;
}
// trying to apply sequentially, the first one wins and we go no further
for (RenameRefactoringContributorEP ep : RenameRefactoringContributorEP.EP_NAME.getExtensions()) {
RenameRefactoringContributor contributor = ep.getContribitor();
if (contributor.isAvailableFor(node)) {
contributor.invoke(project, node);
return;
}
}
}
});
}
}