- KT-2353 convert a selection of Java code to Kotlin by copy paste (or context menu) - Apply patch from Sergey Ignatov
#KT-2353 fixed
This commit is contained in:
@@ -161,6 +161,7 @@
|
||||
<extendWordSelectionHandler implementation="org.jetbrains.jet.plugin.editor.wordSelection.JetListSelectioner"/>
|
||||
<typedHandler implementation="org.jetbrains.jet.plugin.editor.KotlinTypedHandler" />
|
||||
|
||||
<copyPastePostProcessor implementation="org.jetbrains.jet.plugin.conversion.copy.JavaCopyPastePostProcessor"/>
|
||||
<lang.documentationProvider language="JAVA" implementationClass="org.jetbrains.jet.plugin.JetQuickDocumentationProvider" order="first"/>
|
||||
<documentationProvider implementation="org.jetbrains.jet.plugin.JetQuickDocumentationProvider"/>
|
||||
<configurationType implementation="org.jetbrains.jet.plugin.run.JetRunConfigurationType"/>
|
||||
@@ -209,6 +210,11 @@
|
||||
icon="/org/jetbrains/jet/plugin/icons/kotlin_13.png"
|
||||
/>
|
||||
|
||||
<applicationService serviceInterface="org.jetbrains.jet.plugin.editor.JetEditorOptions"
|
||||
serviceImplementation="org.jetbrains.jet.plugin.editor.JetEditorOptions"/>
|
||||
<exportable serviceInterface="org.jetbrains.jet.plugin.editor.JetEditorOptions"/>
|
||||
<editorAppearanceConfigurable instance="org.jetbrains.jet.plugin.editor.JetSettingEditorConfigurable"/>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.jet.plugin.intentions.SpecifyTypeExplicitlyAction</className>
|
||||
<category>Kotlin</category>
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2010-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.plugin.conversion.copy;
|
||||
|
||||
import com.intellij.codeInsight.editorActions.TextBlockTransferableData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
|
||||
/**
|
||||
* @author ignatov
|
||||
*/
|
||||
class ConvertedCode implements TextBlockTransferableData {
|
||||
@NotNull
|
||||
public static final DataFlavor DATA_FLAVOR = new DataFlavor(JavaCopyPastePostProcessor.class, "class: JavaCopyPastePostProcessor");
|
||||
private final String data;
|
||||
|
||||
ConvertedCode(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DataFlavor getFlavor() {
|
||||
return DATA_FLAVOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOffsetCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOffsets(int[] offsets, int index) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setOffsets(int[] offsets, int index) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2010-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.plugin.conversion.copy;
|
||||
|
||||
import com.intellij.codeInsight.editorActions.CopyPastePostProcessor;
|
||||
import com.intellij.codeInsight.editorActions.TextBlockTransferableData;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiJavaFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.j2k.Converter;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.plugin.editor.JetEditorOptions;
|
||||
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author ignatov
|
||||
*/
|
||||
public class JavaCopyPastePostProcessor implements CopyPastePostProcessor<TextBlockTransferableData> {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jet.plugin.conversion.copy.JavaCopyPastePostProcessor");
|
||||
|
||||
@Override
|
||||
public TextBlockTransferableData collectTransferableData(@NotNull PsiFile file, Editor editor, @NotNull int[] startOffsets, @NotNull int[] endOffsets) {
|
||||
try {
|
||||
if (!(file instanceof PsiJavaFile)) {
|
||||
return null;
|
||||
}
|
||||
final String eol = System.getProperty("line.separator");
|
||||
List<PsiElement> buffer = getSelectedElements(file, startOffsets, endOffsets);
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
for (PsiElement e : buffer) {
|
||||
String converted = new Converter().elementToKotlin(e);
|
||||
if (!converted.isEmpty()) {
|
||||
result.append(converted).append(eol);
|
||||
}
|
||||
}
|
||||
return new ConvertedCode(StringUtil.convertLineSeparators(result.toString()));
|
||||
} catch (Throwable t) {
|
||||
LOG.error(t);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<PsiElement> getSelectedElements(@NotNull PsiFile file, @NotNull int[] startOffsets, @NotNull int[] endOffsets) {
|
||||
ArrayList<PsiElement> buffer = new ArrayList<PsiElement>();
|
||||
|
||||
assert startOffsets.length == endOffsets.length : "Must have the same length";
|
||||
|
||||
for (int i = 0; i < startOffsets.length; i++) {
|
||||
int startOffset = startOffsets[i];
|
||||
int endOffset = endOffsets[i];
|
||||
PsiElement elem = file.findElementAt(startOffset);
|
||||
while (elem != null && elem.getParent() != null && !(elem.getParent() instanceof PsiFile) &&
|
||||
elem.getParent().getTextRange().getEndOffset() <= endOffset) {
|
||||
elem = elem.getParent();
|
||||
}
|
||||
buffer.add(elem);
|
||||
|
||||
while (elem != null && elem.getTextRange().getEndOffset() < endOffset) {
|
||||
elem = elem.getNextSibling();
|
||||
buffer.add(elem);
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextBlockTransferableData extractTransferableData(@NotNull Transferable content) {
|
||||
try {
|
||||
if (content.isDataFlavorSupported(ConvertedCode.DATA_FLAVOR)) {
|
||||
return (TextBlockTransferableData) content.getTransferData(ConvertedCode.DATA_FLAVOR);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processTransferableData(Project project, @NotNull final Editor editor, @NotNull final RangeMarker bounds, int caretColumn, Ref<Boolean> indented, @NotNull final TextBlockTransferableData value) {
|
||||
try {
|
||||
final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
|
||||
if (!(file instanceof JetFile)) {
|
||||
return;
|
||||
}
|
||||
JetEditorOptions jetEditorOptions = JetEditorOptions.getInstance();
|
||||
boolean needConvert = jetEditorOptions.isEnableJavaToKotlinConversion() && (jetEditorOptions.isDonTShowConversionDialog() || okFromDialog(project));
|
||||
if (needConvert) {
|
||||
if (value instanceof ConvertedCode) {
|
||||
final String text = ((ConvertedCode) value).getData();
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
editor.getDocument().replaceString(bounds.getStartOffset(), bounds.getEndOffset(), text);
|
||||
editor.getCaretModel().moveToOffset(bounds.getStartOffset() + text.length());
|
||||
PsiDocumentManager.getInstance(file.getProject()).commitDocument(editor.getDocument());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
LOG.error(t);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean okFromDialog(@NotNull Project project) {
|
||||
KotlinPasteFromJavaDialog dialog = new KotlinPasteFromJavaDialog(project);
|
||||
dialog.show();
|
||||
return dialog.isOK();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.jet.plugin.conversion.copy.KotlinPasteFromJavaDialog">
|
||||
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="500" height="400"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="746fc" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Clipboard content copied from Java file. Do you want to convert it to Kotlin code?"/>
|
||||
</properties>
|
||||
</component>
|
||||
<vspacer id="b8512">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<component id="98483" class="javax.swing.JCheckBox" binding="donTShowThisCheckBox" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="&Don't show this dialog next time"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
@@ -0,0 +1,54 @@
|
||||
package org.jetbrains.jet.plugin.conversion.copy;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import org.jetbrains.jet.plugin.editor.JetEditorOptions;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* @ignatov
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public class KotlinPasteFromJavaDialog extends DialogWrapper {
|
||||
private JPanel myPanel;
|
||||
private JCheckBox donTShowThisCheckBox;
|
||||
private JButton buttonOK;
|
||||
|
||||
public KotlinPasteFromJavaDialog(Project project) {
|
||||
super(project, true);
|
||||
setModal(true);
|
||||
getRootPane().setDefaultButton(buttonOK);
|
||||
setTitle("Convert Code From Java");
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent createCenterPanel() {
|
||||
return myPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Container getContentPane() {
|
||||
return myPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Action[] createActions() {
|
||||
return new Action[] {getOKAction(), getCancelAction()};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doOKAction() {
|
||||
if (donTShowThisCheckBox.isSelected()) {
|
||||
JetEditorOptions.getInstance().setDonTShowConversionDialog(true);
|
||||
}
|
||||
super.doOKAction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2010-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.plugin.editor;
|
||||
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.util.xmlb.XmlSerializerUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author ignatov
|
||||
*/
|
||||
@State(
|
||||
name = "JetEditorOptions",
|
||||
storages = {
|
||||
@Storage(
|
||||
file = "$APP_CONFIG$/editor.xml"
|
||||
)}
|
||||
)
|
||||
public class JetEditorOptions implements PersistentStateComponent<JetEditorOptions> {
|
||||
private boolean donTShowConversionDialog = false;
|
||||
private boolean enableJavaToKotlinConversion = true;
|
||||
|
||||
public boolean isDonTShowConversionDialog() {
|
||||
return donTShowConversionDialog;
|
||||
}
|
||||
|
||||
public void setDonTShowConversionDialog(boolean donTShowConversionDialog) {
|
||||
this.donTShowConversionDialog = donTShowConversionDialog;
|
||||
}
|
||||
|
||||
public boolean isEnableJavaToKotlinConversion() {
|
||||
return enableJavaToKotlinConversion;
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public void setEnableJavaToKotlinConversion(boolean enableJavaToKotlinConversion) {
|
||||
this.enableJavaToKotlinConversion = enableJavaToKotlinConversion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetEditorOptions getState() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(JetEditorOptions state) {
|
||||
XmlSerializerUtil.copyBean(state, this);
|
||||
}
|
||||
|
||||
public static JetEditorOptions getInstance() {
|
||||
return ServiceManager.getService(JetEditorOptions.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object clone() {
|
||||
try {
|
||||
return super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2010-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.plugin.editor;
|
||||
|
||||
import com.intellij.openapi.options.BeanConfigurable;
|
||||
import com.intellij.openapi.options.UnnamedConfigurable;
|
||||
|
||||
/**
|
||||
* @author ignatov
|
||||
*/
|
||||
public class JetSettingEditorConfigurable extends BeanConfigurable<JetEditorOptions> implements UnnamedConfigurable {
|
||||
public JetSettingEditorConfigurable() {
|
||||
super(JetEditorOptions.getInstance());
|
||||
checkBox("enableJavaToKotlinConversion", "Enable Java To Kotlin Conversion");
|
||||
checkBox("donTShowConversionDialog", "Don't show Java to Kotlin conversion dialog");
|
||||
}
|
||||
}
|
||||
@@ -175,7 +175,9 @@ public class Converter {
|
||||
else if (e instanceof PsiClassInitializer) {
|
||||
members.add(initializerToInitializer((PsiClassInitializer) e));
|
||||
}
|
||||
else if (e instanceof PsiMember) System.out.println(e.getClass() + " " + e.getText());
|
||||
else if (e instanceof PsiMember) {
|
||||
// System.out.println(e.getClass() + " " + e.getText());
|
||||
}
|
||||
}
|
||||
return members;
|
||||
}
|
||||
@@ -219,7 +221,7 @@ public class Converter {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Class classToClass(@NotNull PsiClass psiClass) {
|
||||
public Class classToClass(@NotNull PsiClass psiClass) {
|
||||
final Set<String> modifiers = modifiersListToModifiersSet(psiClass.getModifierList());
|
||||
final List<Field> fields = fieldsToFieldList(psiClass.getFields(), psiClass);
|
||||
final List<Element> typeParameters = elementsToElementList(psiClass.getTypeParameters());
|
||||
@@ -233,7 +235,7 @@ public class Converter {
|
||||
// we try to find super() call and generate class declaration like that: class A(name: String, i : Int) : Base(name)
|
||||
final SuperVisitor visitor = new SuperVisitor();
|
||||
psiClass.accept(visitor);
|
||||
final HashSet<PsiExpressionList> resolvedSuperCallParameters = visitor.getResolvedSuperCallParameters();
|
||||
final Collection<PsiExpressionList> resolvedSuperCallParameters = visitor.getResolvedSuperCallParameters();
|
||||
if (resolvedSuperCallParameters.size() == 1) {
|
||||
baseClassParams.addAll(
|
||||
expressionsToExpressionList(
|
||||
@@ -677,7 +679,7 @@ public class Converter {
|
||||
|
||||
@NotNull
|
||||
public static Set<String> modifiersListToModifiersSet(@Nullable PsiModifierList modifierList) {
|
||||
HashSet<String> modifiersSet = new HashSet<String>();
|
||||
Set<String> modifiersSet = new HashSet<String>();
|
||||
if (modifierList != null) {
|
||||
if (modifierList.hasExplicitModifier(PsiModifier.ABSTRACT)) modifiersSet.add(Modifier.ABSTRACT);
|
||||
if (modifierList.hasModifierProperty(PsiModifier.FINAL)) modifiersSet.add(Modifier.FINAL);
|
||||
|
||||
Reference in New Issue
Block a user