Fix for KT-14205

If detected unfinished expression it passed through, added warning on action "Convert Java to Kotlin", if Java files contains syntax errors.
This commit is contained in:
Simon Ogorodnik
2016-10-10 19:34:03 +03:00
parent efc0763c2f
commit e7635652bc
6 changed files with 62 additions and 2 deletions
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.idea.actions package org.jetbrains.kotlin.idea.actions
import com.intellij.codeInsight.navigation.NavigationUtil
import com.intellij.ide.scratch.ScratchFileService import com.intellij.ide.scratch.ScratchFileService
import com.intellij.ide.scratch.ScratchRootType import com.intellij.ide.scratch.ScratchRootType
import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnAction
@@ -33,8 +34,10 @@ import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileVisitor import com.intellij.openapi.vfs.VirtualFileVisitor
import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiErrorElement
import com.intellij.psi.PsiJavaFile import com.intellij.psi.PsiJavaFile
import com.intellij.psi.PsiManager import com.intellij.psi.PsiManager
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices
import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor
@@ -61,6 +64,8 @@ class JavaToKotlinAction : AnAction() {
} }
} }
val title = "Convert Java to Kotlin"
private fun saveResults(javaFiles: List<PsiJavaFile>, convertedTexts: List<String>): List<VirtualFile> { private fun saveResults(javaFiles: List<PsiJavaFile>, convertedTexts: List<String>): List<VirtualFile> {
val result = ArrayList<VirtualFile>() val result = ArrayList<VirtualFile>()
for ((psiFile, text) in javaFiles.zip(convertedTexts)) { for ((psiFile, text) in javaFiles.zip(convertedTexts)) {
@@ -99,7 +104,7 @@ class JavaToKotlinAction : AnAction() {
converterResult = converter.filesToKotlin(javaFiles, J2kPostProcessor(formatCode = true), ProgressManager.getInstance().progressIndicator) converterResult = converter.filesToKotlin(javaFiles, J2kPostProcessor(formatCode = true), ProgressManager.getInstance().progressIndicator)
} }
val title = "Convert Java to Kotlin"
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously( if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(
{ {
runReadAction(::convert) runReadAction(::convert)
@@ -145,6 +150,30 @@ class JavaToKotlinAction : AnAction() {
override fun actionPerformed(e: AnActionEvent) { override fun actionPerformed(e: AnActionEvent) {
val javaFiles = selectedJavaFiles(e).toList() val javaFiles = selectedJavaFiles(e).toList()
val project = CommonDataKeys.PROJECT.getData(e.dataContext)!! val project = CommonDataKeys.PROJECT.getData(e.dataContext)!!
val firstSyntaxError = javaFiles.asSequence().map { PsiTreeUtil.findChildOfType(it, PsiErrorElement::class.java) }.firstOrNull()
if (firstSyntaxError != null) {
val count = javaFiles.filter { PsiTreeUtil.hasErrorElements(it) }.count()
val question = firstSyntaxError.containingFile.name +
(if (count > 1) " and ${count - 1} more Java files" else " file") +
" contain syntax errors, the conversion result may be incorrect"
val okText = "Investigate Errors"
val cancelText = "Proceed with Conversion"
if (Messages.showOkCancelDialog(
project,
question,
title,
okText,
cancelText,
Messages.getWarningIcon()
) == Messages.OK) {
NavigationUtil.activateFileWithPsiElement(firstSyntaxError.navigationElement)
return
}
}
convertFiles(javaFiles, project) convertFiles(javaFiles, project)
} }
@@ -546,7 +546,11 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
return return
} }
val referenceName = expression.referenceName!! val referenceName = expression.referenceName ?: run {
result = LiteralExpression(expression.text).assignNoPrototype()
return
}
val target = expression.resolve() val target = expression.resolve()
val isNullable = target is PsiVariable && isNullable(target) val isNullable = target is PsiVariable && isNullable(target)
@@ -0,0 +1,7 @@
public class JavaClass {
public String v = "";
public void m(String s) {
s.
this.v.
}
}
@@ -0,0 +1,8 @@
// ERROR: The expression cannot be a selector (occur after a dot)
class JavaClass {
var v = ""
fun m(s: String) {
s.
this.v.
}
}
@@ -3003,6 +3003,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/issues/spaceBeforeAssignment.java"); String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/issues/spaceBeforeAssignment.java");
doTest(fileName); doTest(fileName);
} }
@TestMetadata("unfinishedReferenceExpression.java")
public void testUnfinishedReferenceExpression() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/issues/unfinishedReferenceExpression.java");
doTest(fileName);
}
} }
@TestMetadata("j2k/testData/fileOrElement/kotlinApiAccess") @TestMetadata("j2k/testData/fileOrElement/kotlinApiAccess")
@@ -3003,6 +3003,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/issues/spaceBeforeAssignment.java"); String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/issues/spaceBeforeAssignment.java");
doTest(fileName); doTest(fileName);
} }
@TestMetadata("unfinishedReferenceExpression.java")
public void testUnfinishedReferenceExpression() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/issues/unfinishedReferenceExpression.java");
doTest(fileName);
}
} }
@TestMetadata("j2k/testData/fileOrElement/kotlinApiAccess") @TestMetadata("j2k/testData/fileOrElement/kotlinApiAccess")