PY-4387 First version of "Convert Module to Package" refactoring

This commit is contained in:
Mikhail Golubev
2015-03-11 20:07:01 +03:00
parent 89e398ebdf
commit bbbe129589
7 changed files with 132 additions and 0 deletions
+7
View File
@@ -745,6 +745,13 @@
<add-to-group group-id="XDebugger.ValueGroup" anchor="after" relative-to-action="Debugger.Tree.AddToWatches"/>
</action>
<action id="PyConvertModuleToPackage" class="com.jetbrains.python.refactoring.packages.PyConvertModuleToPackageAction"
text="Convert to Package"
description="Create package with the same name and move content of the module to __init__.py">
<add-to-group group-id="ProjectViewPopupMenu"/>
<add-to-group group-id="EditorTabPopupMenu"/>
</action>
</actions>
<extensions defaultExtensionNs="com.intellij.spellchecker">
@@ -0,0 +1,83 @@
package com.jetbrains.python.refactoring.packages;
import com.google.common.annotations.VisibleForTesting;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiManager;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.PyFile;
import com.jetbrains.python.psi.PyUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import static com.jetbrains.python.psi.PyUtil.as;
/**
* @author Mikhail Golubev
*/
public class PyConvertModuleToPackageAction extends AnAction {
private static final Logger LOG = Logger.getInstance(PyConvertModuleToPackageAction.class);
@Override
public void actionPerformed(AnActionEvent e) {
final PyFile pyFile = getPythonFile(e);
assert pyFile != null;
final Project project = e.getProject();
if (project != null) {
createPackageFromModule(pyFile, project);
}
}
@VisibleForTesting
public static void createPackageFromModule(@NotNull final PyFile file, @NotNull Project project) {
WriteCommandAction.runWriteCommandAction(project, new Runnable() {
public void run() {
final VirtualFile vFile = file.getVirtualFile();
final VirtualFile parentDir = vFile.getParent();
try {
final VirtualFile packageDir = parentDir.createChildDirectory(this, vFile.getNameWithoutExtension());
vFile.move(this, packageDir);
vFile.rename(this, PyNames.INIT_DOT_PY);
}
catch (IOException e) {
LOG.error(e);
}
}
});
}
@Override
public void update(AnActionEvent e) {
final boolean enabled = isEnabled(e);
e.getPresentation().setVisible(enabled);
e.getPresentation().setEnabled(enabled);
}
@Nullable
private static PyFile getPythonFile(@NotNull AnActionEvent e) {
final VirtualFile vFile = e.getData(CommonDataKeys.VIRTUAL_FILE);
final Project project = e.getData(CommonDataKeys.PROJECT);
if (project != null && vFile != null && !vFile.isDirectory()) {
final PsiManager psiManager = PsiManager.getInstance(project);
return as(psiManager.findFile(vFile), PyFile.class);
}
return null;
}
private static boolean isEnabled(@NotNull AnActionEvent e) {
final Project project = e.getData(CommonDataKeys.PROJECT);
if (project == null) {
return false;
}
final PyFile file = getPythonFile(e);
return file != null && !PyUtil.isPackage(file);
}
}
@@ -0,0 +1,5 @@
import b
def func():
print(b)
@@ -0,0 +1,5 @@
import b
def func():
print(b)
@@ -0,0 +1,32 @@
package com.jetbrains.python.refactoring;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.PlatformTestUtil;
import com.jetbrains.python.fixtures.PyTestCase;
import com.jetbrains.python.psi.PyFile;
import static com.jetbrains.python.refactoring.packages.PyConvertModuleToPackageAction.createPackageFromModule;
/**
* @author Mikhail Golubev
*/
public class PyConvertModuleToPackageTest extends PyTestCase {
// PY-4387
public void testSimple() throws Exception {
final String rootBeforePath = getTestName(true) + "/before";
final String rootAfterPath = getTestName(true) + "/after";
final VirtualFile copiedDirectory = myFixture.copyDirectoryToProject(rootBeforePath, "");
myFixture.configureByFile("a.py");
final PyFile moduleToConvert = assertInstanceOf(myFixture.getFile(), PyFile.class);
createPackageFromModule(moduleToConvert, myFixture.getProject());
PlatformTestUtil.assertDirectoriesEqual(copiedDirectory, getVirtualFileByName(getTestDataPath() +rootAfterPath));
}
@Override
protected String getTestDataPath() {
return super.getTestDataPath() + "/refactoring/convertModuleToPackage/";
}
}