Refactor converter:

Convert JavaCopyPasteProcessor to kotlin (minor code prettifications)
This commit is contained in:
Pavel V. Talanov
2013-12-19 20:48:22 +04:00
parent 1464d1f7ad
commit da3b43fbf3
3 changed files with 130 additions and 134 deletions
@@ -19,6 +19,7 @@ package org.jetbrains.jet.plugin.conversion.copy;
import com.intellij.codeInsight.editorActions.TextBlockTransferableData;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.datatransfer.DataFlavor;
@@ -29,7 +30,7 @@ class CopiedCode implements TextBlockTransferableData {
private final int[] startOffsets;
private final int[] endOffsets;
public CopiedCode(PsiFile file, int[] startOffsets, int[] endOffsets) {
public CopiedCode(@Nullable PsiFile file, @NotNull int[] startOffsets, @NotNull int[] endOffsets) {
this.file = file;
this.startOffsets = startOffsets;
this.endOffsets = endOffsets;
@@ -56,14 +57,17 @@ class CopiedCode implements TextBlockTransferableData {
return index;
}
@Nullable
public PsiFile getFile() {
return file;
}
@NotNull
public int[] getStartOffsets() {
return startOffsets;
}
@NotNull
public int[] getEndOffsets() {
return endOffsets;
}
@@ -1,133 +0,0 @@
/*
* Copyright 2010-2013 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.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.j2k.Converter;
import org.jetbrains.jet.j2k.J2kPackage;
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;
public class JavaCopyPastePostProcessor implements CopyPastePostProcessor<TextBlockTransferableData> {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jet.plugin.conversion.copy.JavaCopyPastePostProcessor");
private static final String EOL = System.getProperty("line.separator");
@Override
public TextBlockTransferableData collectTransferableData(@NotNull PsiFile file, Editor editor, @NotNull int[] startOffsets, @NotNull int[] endOffsets) {
if (!(file instanceof PsiJavaFile)) {
return null;
}
PsiFile lightFile = PsiFileFactory.getInstance(file.getProject()).createFileFromText(file.getText(), file);
return new CopiedCode(lightFile, startOffsets, endOffsets);
}
@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(CopiedCode.DATA_FLAVOR)) {
return (TextBlockTransferableData) content.getTransferData(CopiedCode.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 TextBlockTransferableData value) {
if (!(value instanceof CopiedCode)) return;
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) {
final String text = convertCopiedCodeToKotlin((CopiedCode) value, file);
if (!text.isEmpty()) {
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());
}
});
}
}
}
private static String convertCopiedCodeToKotlin(CopiedCode code, PsiFile file) {
List<PsiElement> buffer = getSelectedElements(code.getFile(), code.getStartOffsets(), code.getEndOffsets());
Project project = file.getProject();
Converter converter = new Converter(project, J2kPackage.getPluginSettings());
StringBuilder result = new StringBuilder();
for (PsiElement e : buffer) {
result.append(converter.elementToKotlin(e));
}
return StringUtil.convertLineSeparators(result.toString());
}
private static boolean okFromDialog(@NotNull Project project) {
KotlinPasteFromJavaDialog dialog = new KotlinPasteFromJavaDialog(project);
dialog.show();
return dialog.isOK();
}
}
@@ -0,0 +1,125 @@
/*
* Copyright 2010-2013 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.*
import org.jetbrains.jet.j2k.*
import org.jetbrains.jet.lang.psi.JetFile
import org.jetbrains.jet.plugin.editor.JetEditorOptions
import java.awt.datatransfer.Transferable
import java.util.ArrayList
public class JavaCopyPastePostProcessor() : CopyPastePostProcessor<TextBlockTransferableData> {
override fun extractTransferableData(content: Transferable?): TextBlockTransferableData? {
try {
if (content!!.isDataFlavorSupported(CopiedCode.DATA_FLAVOR)) {
return (content.getTransferData(CopiedCode.DATA_FLAVOR) as TextBlockTransferableData)
}
}
catch (e: Throwable) {
LOG.error(e)
}
return null
}
public override fun collectTransferableData(file: PsiFile?, editor: Editor?, startOffsets: IntArray?, endOffsets: IntArray?): TextBlockTransferableData? {
if (!(file is PsiJavaFile)) {
return null
}
val lightFile = PsiFileFactory.getInstance(file.getProject())!!.createFileFromText(file.getText()!!, file)
return CopiedCode(lightFile, startOffsets!!, endOffsets!!)
}
public override fun processTransferableData(project: Project?, editor: Editor?, bounds: RangeMarker?,
caretOffset: Int, indented: Ref<Boolean>?, value: TextBlockTransferableData?) {
if (value !is CopiedCode)
return
val file = PsiDocumentManager.getInstance(project!!).getPsiFile(editor!!.getDocument())
if (file !is JetFile)
return
val jetEditorOptions = JetEditorOptions.getInstance()!!
val needConvert = jetEditorOptions.isEnableJavaToKotlinConversion() && (jetEditorOptions.isDonTShowConversionDialog() || okFromDialog(project))
if (needConvert) {
val text = convertCopiedCodeToKotlin((value as CopiedCode), file)
if (text.isNotEmpty() ) {
ApplicationManager.getApplication()!!.runWriteAction {
editor.getDocument().replaceString(bounds!!.getStartOffset(), bounds.getEndOffset(), text)
editor.getCaretModel().moveToOffset(bounds.getStartOffset() + text.length())
PsiDocumentManager.getInstance(file.getProject()).commitDocument(editor.getDocument())
}
}
}
}
private fun convertCopiedCodeToKotlin(code: CopiedCode, file: PsiFile): String {
val buffer = getSelectedElements(code.getFile()!!, code.getStartOffsets(), code.getEndOffsets())
val project = file.getProject()
val converter = Converter(project, PluginSettings)
val result = buffer.map { converter.elementToKotlin(it) }.makeString("")
return StringUtil.convertLineSeparators(result.toString())
}
private fun getSelectedElements(file: PsiFile, startOffsets: IntArray, endOffsets: IntArray): MutableList<PsiElement> {
val buffer = ArrayList<PsiElement>()
assert(startOffsets.size == endOffsets.size) { "Must have the same size" }
for (i in 0..startOffsets.size - 1) {
val startOffset = startOffsets[i]
val endOffset = endOffsets[i]
var elem = file.findElementAt(startOffset)
while (elem != null &&
elem!!.getParent() != null &&
!(elem!!.getParent() is PsiFile) &&
elem!!.getParent()!!.getTextRange()!!.getEndOffset() <= endOffset) {
elem = elem!!.getParent()
}
if (elem != null) {
buffer.add(elem!!)
}
while (elem != null && elem!!.getTextRange()!!.getEndOffset() < endOffset) {
elem = elem!!.getNextSibling()
if (elem != null) {
buffer.add(elem!!)
}
}
}
return buffer
}
private fun okFromDialog(project: Project): Boolean {
val dialog = KotlinPasteFromJavaDialog(project)
dialog.show()
return dialog.isOK()
}
class object {
private val LOG = Logger.getInstance("#org.jetbrains.jet.plugin.conversion.copy.JavaCopyPastePostProcessor")!!
private val EOL = System.getProperty("line.separator")!!
}
}