Conversion on copy paste:
Only convert elements that are wholly selected
This commit is contained in:
@@ -17,7 +17,7 @@
|
|||||||
package org.jetbrains.jet.plugin.conversion.copy;
|
package org.jetbrains.jet.plugin.conversion.copy;
|
||||||
|
|
||||||
import com.intellij.codeInsight.editorActions.TextBlockTransferableData;
|
import com.intellij.codeInsight.editorActions.TextBlockTransferableData;
|
||||||
import com.intellij.psi.PsiFile;
|
import com.intellij.psi.PsiJavaFile;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -26,11 +26,11 @@ import java.awt.datatransfer.DataFlavor;
|
|||||||
class CopiedCode implements TextBlockTransferableData {
|
class CopiedCode implements TextBlockTransferableData {
|
||||||
@NotNull
|
@NotNull
|
||||||
public static final DataFlavor DATA_FLAVOR = new DataFlavor(JavaCopyPastePostProcessor.class, "class: JavaCopyPastePostProcessor");
|
public static final DataFlavor DATA_FLAVOR = new DataFlavor(JavaCopyPastePostProcessor.class, "class: JavaCopyPastePostProcessor");
|
||||||
private final PsiFile file;
|
private final PsiJavaFile file;
|
||||||
private final int[] startOffsets;
|
private final int[] startOffsets;
|
||||||
private final int[] endOffsets;
|
private final int[] endOffsets;
|
||||||
|
|
||||||
public CopiedCode(@Nullable PsiFile file, @NotNull int[] startOffsets, @NotNull int[] endOffsets) {
|
public CopiedCode(@Nullable PsiJavaFile file, @NotNull int[] startOffsets, @NotNull int[] endOffsets) {
|
||||||
this.file = file;
|
this.file = file;
|
||||||
this.startOffsets = startOffsets;
|
this.startOffsets = startOffsets;
|
||||||
this.endOffsets = endOffsets;
|
this.endOffsets = endOffsets;
|
||||||
@@ -58,7 +58,7 @@ class CopiedCode implements TextBlockTransferableData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public PsiFile getFile() {
|
public PsiJavaFile getFile() {
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import org.jetbrains.jet.lang.psi.JetFile
|
|||||||
import org.jetbrains.jet.plugin.editor.JetEditorOptions
|
import org.jetbrains.jet.plugin.editor.JetEditorOptions
|
||||||
import java.awt.datatransfer.Transferable
|
import java.awt.datatransfer.Transferable
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
import com.intellij.openapi.util.TextRange
|
||||||
|
|
||||||
public class JavaCopyPastePostProcessor() : CopyPastePostProcessor<TextBlockTransferableData> {
|
public class JavaCopyPastePostProcessor() : CopyPastePostProcessor<TextBlockTransferableData> {
|
||||||
|
|
||||||
@@ -52,7 +53,7 @@ public class JavaCopyPastePostProcessor() : CopyPastePostProcessor<TextBlockTran
|
|||||||
}
|
}
|
||||||
|
|
||||||
val lightFile = PsiFileFactory.getInstance(file.getProject())!!.createFileFromText(file.getText()!!, file)
|
val lightFile = PsiFileFactory.getInstance(file.getProject())!!.createFileFromText(file.getText()!!, file)
|
||||||
return CopiedCode(lightFile, startOffsets!!, endOffsets!!)
|
return CopiedCode(lightFile as? PsiJavaFile, startOffsets!!, endOffsets!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun processTransferableData(project: Project?, editor: Editor?, bounds: RangeMarker?,
|
public override fun processTransferableData(project: Project?, editor: Editor?, bounds: RangeMarker?,
|
||||||
@@ -60,6 +61,9 @@ public class JavaCopyPastePostProcessor() : CopyPastePostProcessor<TextBlockTran
|
|||||||
if (value !is CopiedCode)
|
if (value !is CopiedCode)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if (value.getFile() == null)
|
||||||
|
return
|
||||||
|
|
||||||
val file = PsiDocumentManager.getInstance(project!!).getPsiFile(editor!!.getDocument())
|
val file = PsiDocumentManager.getInstance(project!!).getPsiFile(editor!!.getDocument())
|
||||||
if (file !is JetFile)
|
if (file !is JetFile)
|
||||||
return
|
return
|
||||||
@@ -67,8 +71,8 @@ public class JavaCopyPastePostProcessor() : CopyPastePostProcessor<TextBlockTran
|
|||||||
val jetEditorOptions = JetEditorOptions.getInstance()!!
|
val jetEditorOptions = JetEditorOptions.getInstance()!!
|
||||||
val needConvert = jetEditorOptions.isEnableJavaToKotlinConversion() && (jetEditorOptions.isDonTShowConversionDialog() || okFromDialog(project))
|
val needConvert = jetEditorOptions.isEnableJavaToKotlinConversion() && (jetEditorOptions.isDonTShowConversionDialog() || okFromDialog(project))
|
||||||
if (needConvert) {
|
if (needConvert) {
|
||||||
val text = convertCopiedCodeToKotlin((value as CopiedCode), file)
|
val text = convertCopiedCodeToKotlin(value, file)
|
||||||
if (text.isNotEmpty() ) {
|
if (text.isNotEmpty()) {
|
||||||
ApplicationManager.getApplication()!!.runWriteAction {
|
ApplicationManager.getApplication()!!.runWriteAction {
|
||||||
editor.getDocument().replaceString(bounds!!.getStartOffset(), bounds.getEndOffset(), text)
|
editor.getDocument().replaceString(bounds!!.getStartOffset(), bounds.getEndOffset(), text)
|
||||||
editor.getCaretModel().moveToOffset(bounds.getStartOffset() + text.length())
|
editor.getCaretModel().moveToOffset(bounds.getStartOffset() + text.length())
|
||||||
@@ -78,38 +82,68 @@ public class JavaCopyPastePostProcessor() : CopyPastePostProcessor<TextBlockTran
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun convertCopiedCodeToKotlin(code: CopiedCode, file: PsiFile): String {
|
private fun convertCopiedCodeToKotlin(code: CopiedCode, fileToPaste: PsiFile): String {
|
||||||
val buffer = getSelectedElements(code.getFile()!!, code.getStartOffsets(), code.getEndOffsets())
|
val converter = Converter(fileToPaste.getProject(), PluginSettings)
|
||||||
val project = file.getProject()
|
val startOffsets = code.getStartOffsets()
|
||||||
val converter = Converter(project, PluginSettings)
|
val endOffsets = code.getEndOffsets()
|
||||||
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" }
|
assert(startOffsets.size == endOffsets.size) { "Must have the same size" }
|
||||||
|
val result = StringBuilder()
|
||||||
for (i in 0..startOffsets.size - 1) {
|
for (i in 0..startOffsets.size - 1) {
|
||||||
val startOffset = startOffsets[i]
|
val startOffset = startOffsets[i]
|
||||||
val endOffset = endOffsets[i]
|
val endOffset = endOffsets[i]
|
||||||
var elem = file.findElementAt(startOffset)
|
result.append(convertRangeToKotlin(code.getFile()!!, TextRange(startOffset, endOffset), converter))
|
||||||
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
|
return StringUtil.convertLineSeparators(result.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun convertRangeToKotlin(file: PsiJavaFile,
|
||||||
|
range: TextRange,
|
||||||
|
converter: Converter): String {
|
||||||
|
val result = StringBuilder()
|
||||||
|
var currentRange = range
|
||||||
|
while (!currentRange.isEmpty()) {
|
||||||
|
val leafElement = findFirstLeafElementWhollyInRange(file, currentRange)
|
||||||
|
if (leafElement == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
val elementToConvert = findTopMostParentWhollyInRange(currentRange, leafElement)
|
||||||
|
result.append(converter.elementToKotlin(elementToConvert))
|
||||||
|
val endOfConverted = elementToConvert.getTextRange()!!.getEndOffset()
|
||||||
|
currentRange = TextRange(endOfConverted, currentRange.getEndOffset())
|
||||||
|
}
|
||||||
|
return result.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findFirstLeafElementWhollyInRange(file: PsiJavaFile, range: TextRange): PsiElement? {
|
||||||
|
var i = range.getStartOffset()
|
||||||
|
while (i < range.getEndOffset()) {
|
||||||
|
var element = file.findElementAt(i)
|
||||||
|
if (element == null) {
|
||||||
|
++i
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val elemRange = element!!.getTextRange()!!
|
||||||
|
if (elemRange !in range) {
|
||||||
|
i = elemRange.getEndOffset()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return element
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findTopMostParentWhollyInRange(range: TextRange,
|
||||||
|
base: PsiElement): PsiElement {
|
||||||
|
var elem = base
|
||||||
|
var parent = elem.getParent()
|
||||||
|
while (elem.getTextRange()!! in range &&
|
||||||
|
parent != null &&
|
||||||
|
parent !is PsiJavaFile &&
|
||||||
|
parent!!.getTextRange()!! in range) {
|
||||||
|
elem = parent!!
|
||||||
|
parent = elem.getParent()
|
||||||
|
}
|
||||||
|
return elem
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun okFromDialog(project: Project): Boolean {
|
private fun okFromDialog(project: Project): Boolean {
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import g.e.v
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import java.util.List;
|
||||||
|
import a.b.c;
|
||||||
|
import java.util.Set;
|
||||||
|
<selection>import g.e.v;</selection>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<caret>
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fun main(args: Array<String>) {
|
||||||
|
reference(arg)
|
||||||
|
somethingElse()
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class A {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
qualifier.<selection>reference(arg)</selection>;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fun main(args: Array<String>) {
|
||||||
|
<caret>
|
||||||
|
somethingElse()
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class A {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
//sdasd
|
||||||
|
}
|
||||||
|
<selection>}</selection>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<caret>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fun main(args: Array<String>) {
|
||||||
|
qualifier
|
||||||
|
somethingElse()
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class A {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
<selection>qualifier</selection>.reference(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fun main(args: Array<String>) {
|
||||||
|
<caret>
|
||||||
|
somethingElse()
|
||||||
|
}
|
||||||
+20
@@ -51,6 +51,26 @@ public class JavaToKotlinCopyPasteConversionTestGenerated extends AbstractJavaTo
|
|||||||
doTest("idea/testData/copyPaste/conversion/Imports2.java");
|
doTest("idea/testData/copyPaste/conversion/Imports2.java");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Imports3.java")
|
||||||
|
public void testImports3() throws Exception {
|
||||||
|
doTest("idea/testData/copyPaste/conversion/Imports3.java");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("MethodReferenceWithoutQualifier.java")
|
||||||
|
public void testMethodReferenceWithoutQualifier() throws Exception {
|
||||||
|
doTest("idea/testData/copyPaste/conversion/MethodReferenceWithoutQualifier.java");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("OnlyClosingBrace.java")
|
||||||
|
public void testOnlyClosingBrace() throws Exception {
|
||||||
|
doTest("idea/testData/copyPaste/conversion/OnlyClosingBrace.java");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("OnlyQualifier.java")
|
||||||
|
public void testOnlyQualifier() throws Exception {
|
||||||
|
doTest("idea/testData/copyPaste/conversion/OnlyQualifier.java");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("SampleBlock.java")
|
@TestMetadata("SampleBlock.java")
|
||||||
public void testSampleBlock() throws Exception {
|
public void testSampleBlock() throws Exception {
|
||||||
doTest("idea/testData/copyPaste/conversion/SampleBlock.java");
|
doTest("idea/testData/copyPaste/conversion/SampleBlock.java");
|
||||||
|
|||||||
Reference in New Issue
Block a user