From e7635652bce2010b8ca83159f150ca2508ca17f8 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 10 Oct 2016 19:34:03 +0300 Subject: [PATCH] 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. --- .../kotlin/idea/actions/JavaToKotlinAction.kt | 31 ++++++++++++++++++- .../kotlin/j2k/ExpressionConverter.kt | 6 +++- .../issues/unfinishedReferenceExpression.java | 7 +++++ .../issues/unfinishedReferenceExpression.kt | 8 +++++ ...otlinConverterForWebDemoTestGenerated.java | 6 ++++ ...otlinConverterSingleFileTestGenerated.java | 6 ++++ 6 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 j2k/testData/fileOrElement/issues/unfinishedReferenceExpression.java create mode 100644 j2k/testData/fileOrElement/issues/unfinishedReferenceExpression.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt b/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt index ee3478fdb83..238aa5cf1b9 100644 --- a/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt +++ b/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.idea.actions +import com.intellij.codeInsight.navigation.NavigationUtil import com.intellij.ide.scratch.ScratchFileService import com.intellij.ide.scratch.ScratchRootType 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.VirtualFileVisitor import com.intellij.psi.PsiDocumentManager +import com.intellij.psi.PsiErrorElement import com.intellij.psi.PsiJavaFile import com.intellij.psi.PsiManager +import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices 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, convertedTexts: List): List { val result = ArrayList() for ((psiFile, text) in javaFiles.zip(convertedTexts)) { @@ -99,7 +104,7 @@ class JavaToKotlinAction : AnAction() { converterResult = converter.filesToKotlin(javaFiles, J2kPostProcessor(formatCode = true), ProgressManager.getInstance().progressIndicator) } - val title = "Convert Java to Kotlin" + if (!ProgressManager.getInstance().runProcessWithProgressSynchronously( { runReadAction(::convert) @@ -145,6 +150,30 @@ class JavaToKotlinAction : AnAction() { override fun actionPerformed(e: AnActionEvent) { val javaFiles = selectedJavaFiles(e).toList() 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) } diff --git a/j2k/src/org/jetbrains/kotlin/j2k/ExpressionConverter.kt b/j2k/src/org/jetbrains/kotlin/j2k/ExpressionConverter.kt index 9b2e0d32a3e..aa262cbe19b 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/ExpressionConverter.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/ExpressionConverter.kt @@ -546,7 +546,11 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter { return } - val referenceName = expression.referenceName!! + val referenceName = expression.referenceName ?: run { + result = LiteralExpression(expression.text).assignNoPrototype() + return + } + val target = expression.resolve() val isNullable = target is PsiVariable && isNullable(target) diff --git a/j2k/testData/fileOrElement/issues/unfinishedReferenceExpression.java b/j2k/testData/fileOrElement/issues/unfinishedReferenceExpression.java new file mode 100644 index 00000000000..60ac2c80a59 --- /dev/null +++ b/j2k/testData/fileOrElement/issues/unfinishedReferenceExpression.java @@ -0,0 +1,7 @@ +public class JavaClass { + public String v = ""; + public void m(String s) { + s. + this.v. + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/issues/unfinishedReferenceExpression.kt b/j2k/testData/fileOrElement/issues/unfinishedReferenceExpression.kt new file mode 100644 index 00000000000..64a6c19e416 --- /dev/null +++ b/j2k/testData/fileOrElement/issues/unfinishedReferenceExpression.kt @@ -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. + } +} \ No newline at end of file diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java index 1465f6797e4..e990c3f6299 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java +++ b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java @@ -3003,6 +3003,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/issues/spaceBeforeAssignment.java"); 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") diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java index 1e4b1201f21..c8b8bd8053c 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java +++ b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java @@ -3003,6 +3003,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/issues/spaceBeforeAssignment.java"); 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")