diff --git a/idea/idea.iml b/idea/idea.iml
index 3b2a3f833e0..d646586b05d 100644
--- a/idea/idea.iml
+++ b/idea/idea.iml
@@ -24,6 +24,7 @@
+
diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index 1ce3fcb7702..ed1525df38a 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -31,6 +31,11 @@
+
+
+
+
diff --git a/idea/src/org/jetbrains/jet/plugin/actions/JavaToKotlinAction.java b/idea/src/org/jetbrains/jet/plugin/actions/JavaToKotlinAction.java
new file mode 100644
index 00000000000..9cc875c21e3
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/actions/JavaToKotlinAction.java
@@ -0,0 +1,86 @@
+package org.jetbrains.jet.plugin.actions;
+
+import com.intellij.ide.highlighter.JavaFileType;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+
+import java.util.List;
+
+import static org.jetbrains.jet.j2k.Converter.clearClassIdentifiers;
+import static org.jetbrains.jet.plugin.actions.JavaToKotlinActionUtil.*;
+
+/**
+ * @author ignatov
+ */
+public class JavaToKotlinAction extends AnAction {
+ @Override
+ public void actionPerformed(final AnActionEvent e) {
+ VirtualFile[] virtualFiles = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY);
+ final Project project = PlatformDataKeys.PROJECT.getData(e.getDataContext());
+ assert virtualFiles != null;
+ assert project != null;
+ int result = Messages.showYesNoCancelDialog(project,
+ "Would you like to backup Java files?",
+ "Backup",
+ Messages.getQuestionIcon());
+ final boolean finalRemoveIt = needToRemoveFiles(result);
+ final List allJavaFiles = getAllJavaFiles(virtualFiles, project);
+
+ clearClassIdentifiers();
+ for (PsiFile f : allJavaFiles) {
+ if (f.getFileType() instanceof JavaFileType) {
+ setClassIdentifiers(f);
+ }
+ }
+
+ final List allJavaFilesNear = getAllJavaFiles(virtualFiles, project);
+ CommandProcessor.getInstance().executeCommand(
+ project,
+ new Runnable() {
+ @Override
+ public void run() {
+ final List newFiles = performFiles(allJavaFilesNear);
+ if (finalRemoveIt) {
+ deleteFiles(allJavaFilesNear);
+ }
+ else {
+ renameFiles(allJavaFiles);
+ }
+ reformatFiles(newFiles, project);
+ for (VirtualFile vf : newFiles) {
+ FileEditorManager.getInstance(project).openFile(vf, true);
+ }
+ }
+ },
+ "Convert files from Java to Kotlin",
+ "group_id"
+ );
+ }
+
+ private static boolean needToRemoveFiles(int result) {
+ boolean removeIt = false;
+ switch (result) {
+ case 0:
+ removeIt = false;
+ break;
+ case 1:
+ removeIt = true;
+ break;
+ }
+ return removeIt;
+ }
+
+ @Override
+ public void update(AnActionEvent e) {
+ final boolean enabled = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY) != null;
+ e.getPresentation().setVisible(enabled);
+ e.getPresentation().setEnabled(enabled);
+ }
+}
diff --git a/idea/src/org/jetbrains/jet/plugin/actions/JavaToKotlinActionUtil.java b/idea/src/org/jetbrains/jet/plugin/actions/JavaToKotlinActionUtil.java
new file mode 100644
index 00000000000..831874d25a8
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/actions/JavaToKotlinActionUtil.java
@@ -0,0 +1,154 @@
+package org.jetbrains.jet.plugin.actions;
+
+import com.intellij.ide.highlighter.JavaFileType;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.ex.MessagesEx;
+import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiJavaFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.codeStyle.CodeStyleManager;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jet.j2k.Converter;
+import org.jetbrains.jet.j2k.visitors.ClassVisitor;
+
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * @author ignatov
+ */
+public class JavaToKotlinActionUtil {
+ private JavaToKotlinActionUtil() {
+ }
+
+ static void setClassIdentifiers(@NotNull PsiFile psiFile) {
+ ClassVisitor c = new ClassVisitor();
+ psiFile.accept(c);
+ Converter.setClassIdentifiers(c.getClassIdentifiers());
+ }
+
+ @NotNull
+ private static List getChildrenRecursive(@Nullable VirtualFile baseDir) {
+ List result = new LinkedList();
+ VirtualFile[] children = baseDir != null ? baseDir.getChildren() : VirtualFile.EMPTY_ARRAY;
+ result.addAll(Arrays.asList(children));
+ for (VirtualFile f : children)
+ result.addAll(getChildrenRecursive(f));
+ return result;
+ }
+
+ @NotNull
+ static List getAllJavaFiles(@NotNull VirtualFile[] vFiles, Project project) {
+ final PsiManager manager = PsiManager.getInstance(project);
+ Set filesSet = new HashSet();
+ for (VirtualFile f : vFiles) {
+ filesSet.add(f);
+ filesSet.addAll(getChildrenRecursive(f));
+ }
+ final List res = new ArrayList();
+ for (final VirtualFile file : filesSet) {
+ final PsiFile psiFile = manager.findFile(file);
+ if (psiFile != null && psiFile.getFileType() instanceof JavaFileType) {
+ res.add(psiFile);
+ }
+ }
+ return res;
+ }
+
+ static void reformatFiles(List allJetFiles, final Project project) {
+ for (final VirtualFile vf : allJetFiles)
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ if (vf != null) {
+ PsiFile psiFile = PsiManager.getInstance(project).findFile(vf);
+ if (psiFile != null) {
+ CodeStyleManager.getInstance(project).reformat(psiFile);
+ }
+ }
+ }
+ });
+ }
+
+ @NotNull
+ static List performFiles(List allJavaFilesNear) {
+ final List result = new LinkedList();
+ for (final PsiFile f : allJavaFilesNear) {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ VirtualFile vf = performOneFile(f);
+ if (vf != null) {
+ result.add(vf);
+ }
+ }
+ });
+ }
+ return result;
+ }
+
+ static void deleteFiles(List allJavaFilesNear) {
+ for (final PsiFile f : allJavaFilesNear) {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ PsiManager manager = f.getManager();
+ VirtualFile vFile = f.getVirtualFile();
+ if (vFile != null) {
+ vFile.delete(manager);
+ }
+ } catch (IOException ignored) {
+ }
+ }
+ });
+ }
+ }
+
+ @Nullable
+ private static VirtualFile performOneFile(PsiFile psiFile) {
+ try {
+ VirtualFile virtualFile = psiFile.getVirtualFile();
+ if (psiFile instanceof PsiJavaFile && virtualFile != null) {
+ String result = "";
+ try {
+ result = Converter.fileToFile((PsiJavaFile) psiFile).toKotlin();
+ } catch (Exception e) {
+ //noinspection CallToPrintStackTrace
+ e.printStackTrace();
+ }
+ final PsiManager manager = psiFile.getManager();
+ assert manager != null;
+ VirtualFile copy = virtualFile.copy(manager, virtualFile.getParent(), virtualFile.getNameWithoutExtension() + ".kt");
+ copy.setBinaryContent(CharsetToolkit.getUtf8Bytes(result));
+ return copy;
+ }
+ } catch (Exception ex) {
+ MessagesEx.error(psiFile.getProject(), ex.getMessage()).showLater();
+ }
+ return null;
+ }
+
+ static void renameFiles(@NotNull List psiFiles) {
+ for (final PsiFile f : psiFiles) {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ PsiManager manager = f.getManager();
+ VirtualFile vFile = f.getVirtualFile();
+ if (vFile != null) {
+ vFile.copy(manager, vFile.getParent(), vFile.getNameWithoutExtension() + ".java.old");
+ vFile.delete(manager);
+ }
+ } catch (IOException ignored) {
+ }
+ }
+ });
+ }
+ }
+}